Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Jul 2011 16:55:45 +0000 (09:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 24 Jul 2011 16:55:45 +0000 (09:55 -0700)
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: (21 commits)
  [S390] use siginfo for sigtrap signals
  [S390] dasd: add enhanced DASD statistics interface
  [S390] kvm: make sigp emerg smp capable
  [S390] disable cpu measurement alerts on a dying cpu
  [S390] initial cr0 bits
  [S390] iucv cr0 enablement bit
  [S390] race safe external interrupt registration
  [S390] remove tape block docu
  [S390] ap: toleration support for ap device type 10
  [S390] cleanup program check handler prototypes
  [S390] remove kvm mmu reload on s390
  [S390] Use gmap translation for accessing guest memory
  [S390] use gmap address spaces for kvm guest images
  [S390] kvm guest address space mapping
  [S390] fix s390 assembler code alignments
  [S390] move sie code to entry.S
  [S390] kvm: handle tprot intercepts
  [S390] qdio: clear shared DSCI before scheduling the queue handler
  [S390] reference bit testing for unmapped pages
  [S390] irqs: Do not trace arch_local_{*,irq_*} functions
  ...

60 files changed:
Documentation/s390/TAPE [deleted file]
arch/s390/boot/compressed/head31.S
arch/s390/boot/compressed/head64.S
arch/s390/include/asm/irqflags.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/linkage.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/mmu.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/tlbflush.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/base.S
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/entry.S
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/head.S
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/irq.c
arch/s390/kernel/mcount.S
arch/s390/kernel/mcount64.S
arch/s390/kernel/reipl.S
arch/s390/kernel/reipl64.S
arch/s390/kernel/relocate_kernel.S
arch/s390/kernel/relocate_kernel64.S
arch/s390/kernel/s390_ksyms.c
arch/s390/kernel/sclp.S
arch/s390/kernel/smp.c
arch/s390/kernel/switch_cpu.S
arch/s390/kernel/switch_cpu64.S
arch/s390/kernel/swsusp_asm64.S
arch/s390/kernel/traps.c
arch/s390/kvm/Makefile
arch/s390/kvm/gaccess.h
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/kvm/sie64a.S [deleted file]
arch/s390/kvm/sigp.c
arch/s390/lib/qrnnd.S
arch/s390/mm/fault.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/pgtable.c
arch/s390/mm/vmem.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/Kconfig
drivers/s390/cio/qdio_thinint.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
mm/rmap.c
net/iucv/iucv.c

diff --git a/Documentation/s390/TAPE b/Documentation/s390/TAPE
deleted file mode 100644 (file)
index c639aa5..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-Channel attached Tape device driver 
-
------------------------------WARNING-----------------------------------------
-This driver is considered to be EXPERIMENTAL. Do NOT use it in 
-production environments. Feel free to test it and report problems back to us. 
------------------------------------------------------------------------------
-
-The LINUX for zSeries tape device driver manages channel attached tape drives 
-which are compatible to IBM 3480 or IBM 3490 magnetic tape subsystems. This 
-includes various models of these devices (for example the 3490E). 
-
-
-Tape driver features 
-
-The device driver supports a maximum of 128 tape devices. 
-No official LINUX device major number is assigned to the zSeries tape device 
-driver. It allocates major numbers dynamically and reports them on system 
-startup. 
-Typically it will get major number 254 for both the character device front-end 
-and the block device front-end. 
-
-The tape device driver needs no kernel parameters. All supported devices 
-present are detected on driver initialization at system startup or module load.
-The devices detected are ordered by their subchannel numbers. The device with 
-the lowest subchannel number becomes device 0, the next one will be device 1 
-and so on. 
-
-
-Tape character device front-end 
-
-The usual way to read or write to the tape device is through the character 
-device front-end. The zSeries tape device driver provides two character devices
-for each physical device -- the first of these will rewind automatically when 
-it is closed, the second will not rewind automatically. 
-
-The character device nodes are named /dev/rtibm0 (rewinding) and /dev/ntibm0 
-(non-rewinding) for the first device, /dev/rtibm1 and /dev/ntibm1 for the 
-second, and so on. 
-
-The character device front-end can be used as any other LINUX tape device. You 
-can write to it and read from it using LINUX facilities such as GNU tar. The 
-tool mt can be used to perform control operations, such as rewinding the tape 
-or skipping a file. 
-
-Most LINUX tape software should work with either tape character device. 
-
-
-Tape block device front-end 
-
-The tape device may also be accessed as a block device in read-only mode. 
-This could be used for software installation in the same way as it is used with 
-other operation systems on the zSeries platform (and most LINUX 
-distributions are shipped on compact disk using ISO9660 filesystems). 
-
-One block device node is provided for each physical device. These are named 
-/dev/btibm0 for the first device, /dev/btibm1 for the second and so on. 
-You should only use the ISO9660 filesystem on LINUX for zSeries tapes because 
-the physical tape devices cannot perform fast seeks and the ISO9660 system is 
-optimized for this situation. 
-
-
-Tape block device example 
-
-In this example a tape with an ISO9660 filesystem is created using the first 
-tape device. ISO9660 filesystem support must be built into your system kernel
-for this. 
-The mt command is used to issue tape commands and the mkisofs command to 
-create an ISO9660 filesystem: 
-
-- create a LINUX directory (somedir) with the contents of the filesystem 
-     mkdir somedir
-     cp contents somedir 
-
-- insert a tape 
-
-- ensure the tape is at the beginning 
-     mt -f /dev/ntibm0 rewind 
-
-- set the blocksize of the character driver. The blocksize 2048 bytes
-  is commonly used on ISO9660 CD-Roms
-     mt -f /dev/ntibm0 setblk 2048 
-
-- write the filesystem to the character device driver 
-     mkisofs -o /dev/ntibm0 somedir 
-
-- rewind the tape again 
-     mt -f /dev/ntibm0 rewind 
-
-- Now you can mount your new filesystem as a block device: 
-     mount -t iso9660 -o ro,block=2048 /dev/btibm0 /mnt 
-
-TODO List 
-
-   - Driver has to be stabilized still
-
-BUGS 
-
-This driver is considered BETA, which means some weaknesses may still
-be in it.
-If an error occurs which cannot be handled by the code you will get a 
-sense-data dump.In that case please do the following: 
-
-1. set the tape driver debug level to maximum: 
-     echo 6 >/proc/s390dbf/tape/level 
-
-2. re-perform the actions which produced the bug. (Hopefully the bug will 
-   reappear.) 
-
-3. get a snapshot from the debug-feature: 
-     cat /proc/s390dbf/tape/hex_ascii >somefile 
-
-4. Now put the snapshot together with a detailed description of the situation 
-   that led to the bug: 
- - Which tool did you use? 
- - Which hardware do you have? 
- - Was your tape unit online? 
- - Is it a shared tape unit? 
-
-5. Send an email with your bug report to: 
-     mailto:Linux390@de.ibm.com 
-
-
index 2a5523a..e8c9e18 100644 (file)
@@ -7,14 +7,14 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include "sizes.h"
 
 __HEAD
-       .globl  startup_continue
-startup_continue:
+ENTRY(startup_continue)
        basr    %r13,0                  # get base
 .LPG1:
        # setup stack
index 2982cb1..f86a4ee 100644 (file)
@@ -7,14 +7,14 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include "sizes.h"
 
 __HEAD
-       .globl  startup_continue
-startup_continue:
+ENTRY(startup_continue)
        basr    %r13,0                  # get base
 .LPG1:
        # setup stack
index 865d6d8..38fdf45 100644 (file)
 })
 
 /* set system mask. */
-static inline void __arch_local_irq_ssm(unsigned long flags)
+static inline notrace void __arch_local_irq_ssm(unsigned long flags)
 {
        asm volatile("ssm   %0" : : "Q" (flags) : "memory");
 }
 
-static inline unsigned long arch_local_save_flags(void)
+static inline notrace unsigned long arch_local_save_flags(void)
 {
        return __arch_local_irq_stosm(0x00);
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline notrace unsigned long arch_local_irq_save(void)
 {
        return __arch_local_irq_stnsm(0xfc);
 }
 
-static inline void arch_local_irq_disable(void)
+static inline notrace void arch_local_irq_disable(void)
 {
        arch_local_irq_save();
 }
 
-static inline void arch_local_irq_enable(void)
+static inline notrace void arch_local_irq_enable(void)
 {
        __arch_local_irq_stosm(0x03);
 }
 
-static inline void arch_local_irq_restore(unsigned long flags)
+static inline notrace void arch_local_irq_restore(unsigned long flags)
 {
        __arch_local_irq_ssm(flags);
 }
 
-static inline bool arch_irqs_disabled_flags(unsigned long flags)
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
 {
        return !(flags & (3UL << (BITS_PER_LONG - 8)));
 }
 
-static inline bool arch_irqs_disabled(void)
+static inline notrace bool arch_irqs_disabled(void)
 {
        return arch_irqs_disabled_flags(arch_local_save_flags());
 }
index cef7dbf..00ff00d 100644 (file)
@@ -93,9 +93,7 @@ struct kvm_s390_sie_block {
        __u32   scaol;                  /* 0x0064 */
        __u8    reserved68[4];          /* 0x0068 */
        __u32   todpr;                  /* 0x006c */
-       __u8    reserved70[16];         /* 0x0070 */
-       __u64   gmsor;                  /* 0x0080 */
-       __u64   gmslm;                  /* 0x0088 */
+       __u8    reserved70[32];         /* 0x0070 */
        psw_t   gpsw;                   /* 0x0090 */
        __u64   gg14;                   /* 0x00a0 */
        __u64   gg15;                   /* 0x00a8 */
@@ -138,6 +136,7 @@ struct kvm_vcpu_stat {
        u32 instruction_chsc;
        u32 instruction_stsi;
        u32 instruction_stfl;
+       u32 instruction_tprot;
        u32 instruction_sigp_sense;
        u32 instruction_sigp_emergency;
        u32 instruction_sigp_stop;
@@ -175,6 +174,10 @@ struct kvm_s390_prefix_info {
        __u32 address;
 };
 
+struct kvm_s390_emerg_info {
+       __u16 code;
+};
+
 struct kvm_s390_interrupt_info {
        struct list_head list;
        u64     type;
@@ -182,6 +185,7 @@ struct kvm_s390_interrupt_info {
                struct kvm_s390_io_info io;
                struct kvm_s390_ext_info ext;
                struct kvm_s390_pgm_info pgm;
+               struct kvm_s390_emerg_info emerg;
                struct kvm_s390_prefix_info prefix;
        };
 };
@@ -226,6 +230,7 @@ struct kvm_vcpu_arch {
                struct cpuid    cpu_id;
                u64             stidp_data;
        };
+       struct gmap *gmap;
 };
 
 struct kvm_vm_stat {
@@ -236,6 +241,7 @@ struct kvm_arch{
        struct sca_block *sca;
        debug_info_t *dbf;
        struct kvm_s390_float_interrupt float_int;
+       struct gmap *gmap;
 };
 
 extern int sie64a(struct kvm_s390_sie_block *, unsigned long *);
index 291c2d0..fc8a828 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __ASM_LINKAGE_H
 #define __ASM_LINKAGE_H
 
-/* Nothing to see here... */
+#include <linux/stringify.h>
+
+#define __ALIGN .align 4, 0x07
+#define __ALIGN_STR __stringify(__ALIGN)
 
 #endif
index 228cf0b..f26280d 100644 (file)
@@ -268,7 +268,7 @@ struct _lowcore {
        __u64   vdso_per_cpu_data;              /* 0x0358 */
        __u64   machine_flags;                  /* 0x0360 */
        __u64   ftrace_func;                    /* 0x0368 */
-       __u64   sie_hook;                       /* 0x0370 */
+       __u64   gmap;                           /* 0x0370 */
        __u64   cmf_hpp;                        /* 0x0378 */
 
        /* Interrupt response block. */
index 82d0847..4506791 100644 (file)
@@ -6,6 +6,7 @@ typedef struct {
        unsigned int flush_mm;
        spinlock_t list_lock;
        struct list_head pgtable_list;
+       struct list_head gmap_list;
        unsigned long asce_bits;
        unsigned long asce_limit;
        unsigned long vdso_base;
@@ -17,6 +18,7 @@ typedef struct {
 
 #define INIT_MM_CONTEXT(name)                                                \
        .context.list_lock    = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \
-       .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),
+       .context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),    \
+       .context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list),
 
 #endif
index 38e71eb..8eef9b5 100644 (file)
@@ -20,7 +20,7 @@
 unsigned long *crst_table_alloc(struct mm_struct *);
 void crst_table_free(struct mm_struct *, unsigned long *);
 
-unsigned long *page_table_alloc(struct mm_struct *);
+unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
 void page_table_free(struct mm_struct *, unsigned long *);
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
 void page_table_free_rcu(struct mmu_gather *, unsigned long *);
@@ -115,6 +115,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        spin_lock_init(&mm->context.list_lock);
        INIT_LIST_HEAD(&mm->context.pgtable_list);
+       INIT_LIST_HEAD(&mm->context.gmap_list);
        return (pgd_t *) crst_table_alloc(mm);
 }
 #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
@@ -133,8 +134,8 @@ static inline void pmd_populate(struct mm_struct *mm,
 /*
  * page table entry allocation/free routines.
  */
-#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
-#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
+#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
+#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))
 
 #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
 #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
index 801fbe1..519eb5f 100644 (file)
@@ -654,6 +654,48 @@ static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
 #endif
 }
 
+/**
+ * struct gmap_struct - guest address space
+ * @mm: pointer to the parent mm_struct
+ * @table: pointer to the page directory
+ * @crst_list: list of all crst tables used in the guest address space
+ */
+struct gmap {
+       struct list_head list;
+       struct mm_struct *mm;
+       unsigned long *table;
+       struct list_head crst_list;
+};
+
+/**
+ * struct gmap_rmap - reverse mapping for segment table entries
+ * @next: pointer to the next gmap_rmap structure in the list
+ * @entry: pointer to a segment table entry
+ */
+struct gmap_rmap {
+       struct list_head list;
+       unsigned long *entry;
+};
+
+/**
+ * struct gmap_pgtable - gmap information attached to a page table
+ * @vmaddr: address of the 1MB segment in the process virtual memory
+ * @mapper: list of segment table entries maping a page table
+ */
+struct gmap_pgtable {
+       unsigned long vmaddr;
+       struct list_head mapper;
+};
+
+struct gmap *gmap_alloc(struct mm_struct *mm);
+void gmap_free(struct gmap *gmap);
+void gmap_enable(struct gmap *gmap);
+void gmap_disable(struct gmap *gmap);
+int gmap_map_segment(struct gmap *gmap, unsigned long from,
+                    unsigned long to, unsigned long length);
+int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long gmap_fault(unsigned long address, struct gmap *);
+
 /*
  * Certain architectures need to do special things when PTEs
  * within a page table are directly modified.  Thus, the following
index 1300c30..55dfcc8 100644 (file)
@@ -80,6 +80,7 @@ struct thread_struct {
        mm_segment_t mm_segment;
         unsigned long prot_addr;        /* address of protection-excep.     */
         unsigned int trap_no;
+       unsigned long gmap_addr;        /* address of last gmap fault. */
        struct per_regs per_user;       /* User specified PER registers */
        struct per_event per_event;     /* Cause of the last PER trap */
         /* pfault_wait is used to block the process on a pfault event */
index ad1382f..1a5dbb6 100644 (file)
@@ -94,6 +94,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT      9       /* syscall auditing active */
 #define TIF_SECCOMP            10      /* secure computing */
 #define TIF_SYSCALL_TRACEPOINT 11      /* syscall tracepoint instrumentation */
+#define TIF_SIE                        12      /* guest execution active */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling
                                           TIF_NEED_RESCHED */
 #define TIF_31BIT              17      /* 32bit process */
@@ -113,6 +114,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_TRACEPOINT        (1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_SIE               (1<<TIF_SIE)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT             (1<<TIF_31BIT)
 #define _TIF_SINGLE_STEP       (1<<TIF_FREEZE)
index b7a4f2e..3044453 100644 (file)
@@ -80,7 +80,7 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
         * on all cpus instead of doing a local flush if the mm
         * only ran on the local cpu.
         */
-       if (MACHINE_HAS_IDTE)
+       if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list))
                __tlb_flush_idte((unsigned long) mm->pgd |
                                 mm->context.asce_bits);
        else
index edfbd17..05d8f38 100644 (file)
@@ -151,7 +151,7 @@ int main(void)
        DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area));
        DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
        DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
-       DEFINE(__LC_SIE_HOOK, offsetof(struct _lowcore, sie_hook));
+       DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap));
        DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp));
 #endif /* CONFIG_32BIT */
        return 0;
index 15e46ca..209938c 100644 (file)
@@ -6,13 +6,13 @@
  *              Michael Holzheu <holzheu@de.ibm.com>
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_64BIT
 
-       .globl  s390_base_mcck_handler
-s390_base_mcck_handler:
+ENTRY(s390_base_mcck_handler)
        basr    %r13,0
 0:     lg      %r15,__LC_PANIC_STACK   # load panic stack
        aghi    %r15,-STACK_FRAME_OVERHEAD
@@ -26,13 +26,13 @@ s390_base_mcck_handler:
        lpswe   __LC_MCK_OLD_PSW
 
        .section .bss
+       .align 8
        .globl  s390_base_mcck_handler_fn
 s390_base_mcck_handler_fn:
        .quad   0
        .previous
 
-       .globl  s390_base_ext_handler
-s390_base_ext_handler:
+ENTRY(s390_base_ext_handler)
        stmg    %r0,%r15,__LC_SAVE_AREA
        basr    %r13,0
 0:     aghi    %r15,-STACK_FRAME_OVERHEAD
@@ -46,13 +46,13 @@ s390_base_ext_handler:
        lpswe   __LC_EXT_OLD_PSW
 
        .section .bss
+       .align 8
        .globl s390_base_ext_handler_fn
 s390_base_ext_handler_fn:
        .quad   0
        .previous
 
-       .globl  s390_base_pgm_handler
-s390_base_pgm_handler:
+ENTRY(s390_base_pgm_handler)
        stmg    %r0,%r15,__LC_SAVE_AREA
        basr    %r13,0
 0:     aghi    %r15,-STACK_FRAME_OVERHEAD
@@ -70,6 +70,7 @@ disabled_wait_psw:
        .quad   0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler
 
        .section .bss
+       .align 8
        .globl s390_base_pgm_handler_fn
 s390_base_pgm_handler_fn:
        .quad   0
@@ -77,8 +78,7 @@ s390_base_pgm_handler_fn:
 
 #else /* CONFIG_64BIT */
 
-       .globl  s390_base_mcck_handler
-s390_base_mcck_handler:
+ENTRY(s390_base_mcck_handler)
        basr    %r13,0
 0:     l       %r15,__LC_PANIC_STACK   # load panic stack
        ahi     %r15,-STACK_FRAME_OVERHEAD
@@ -93,13 +93,13 @@ s390_base_mcck_handler:
 2:     .long   s390_base_mcck_handler_fn
 
        .section .bss
+       .align 4
        .globl  s390_base_mcck_handler_fn
 s390_base_mcck_handler_fn:
        .long   0
        .previous
 
-       .globl  s390_base_ext_handler
-s390_base_ext_handler:
+ENTRY(s390_base_ext_handler)
        stm     %r0,%r15,__LC_SAVE_AREA
        basr    %r13,0
 0:     ahi     %r15,-STACK_FRAME_OVERHEAD
@@ -115,13 +115,13 @@ s390_base_ext_handler:
 2:     .long   s390_base_ext_handler_fn
 
        .section .bss
+       .align 4
        .globl  s390_base_ext_handler_fn
 s390_base_ext_handler_fn:
        .long   0
        .previous
 
-       .globl  s390_base_pgm_handler
-s390_base_pgm_handler:
+ENTRY(s390_base_pgm_handler)
        stm     %r0,%r15,__LC_SAVE_AREA
        basr    %r13,0
 0:     ahi     %r15,-STACK_FRAME_OVERHEAD
@@ -142,6 +142,7 @@ disabled_wait_psw:
        .long   0x000a0000,0x00000000 + s390_base_pgm_handler
 
        .section .bss
+       .align 4
        .globl  s390_base_pgm_handler_fn
 s390_base_pgm_handler_fn:
        .long   0
index 1f5eb78..08ab9aa 100644 (file)
@@ -7,86 +7,74 @@
 *              Thomas Spatzier (tspat@de.ibm.com)
 */
 
-       .globl  sys32_exit_wrapper
-sys32_exit_wrapper:
+#include <linux/linkage.h>
+
+ENTRY(sys32_exit_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_exit                # branch to sys_exit
 
-       .globl  sys32_read_wrapper
-sys32_read_wrapper:
+ENTRY(sys32_read_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # char *
        llgfr   %r4,%r4                 # size_t
        jg      sys32_read              # branch to sys_read
 
-       .globl  sys32_write_wrapper
-sys32_write_wrapper:
+ENTRY(sys32_write_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # size_t
        jg      sys32_write             # branch to system call
 
-       .globl  sys32_open_wrapper
-sys32_open_wrapper:
+ENTRY(sys32_open_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
        jg      sys_open                # branch to system call
 
-       .globl  sys32_close_wrapper
-sys32_close_wrapper:
+ENTRY(sys32_close_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_close               # branch to system call
 
-       .globl  sys32_creat_wrapper
-sys32_creat_wrapper:
+ENTRY(sys32_creat_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_creat               # branch to system call
 
-       .globl  sys32_link_wrapper
-sys32_link_wrapper:
+ENTRY(sys32_link_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_link                # branch to system call
 
-       .globl  sys32_unlink_wrapper
-sys32_unlink_wrapper:
+ENTRY(sys32_unlink_wrapper)
        llgtr   %r2,%r2                 # const char *
        jg      sys_unlink              # branch to system call
 
-       .globl  sys32_chdir_wrapper
-sys32_chdir_wrapper:
+ENTRY(sys32_chdir_wrapper)
        llgtr   %r2,%r2                 # const char *
        jg      sys_chdir               # branch to system call
 
-       .globl  sys32_time_wrapper
-sys32_time_wrapper:
+ENTRY(sys32_time_wrapper)
        llgtr   %r2,%r2                 # int *
        jg      compat_sys_time         # branch to system call
 
-       .globl  sys32_mknod_wrapper
-sys32_mknod_wrapper:
+ENTRY(sys32_mknod_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        llgfr   %r4,%r4                 # dev
        jg      sys_mknod               # branch to system call
 
-       .globl  sys32_chmod_wrapper
-sys32_chmod_wrapper:
+ENTRY(sys32_chmod_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # mode_t
        jg      sys_chmod               # branch to system call
 
-       .globl  sys32_lchown16_wrapper
-sys32_lchown16_wrapper:
+ENTRY(sys32_lchown16_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
        llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t
        jg      sys32_lchown16          # branch to system call
 
-       .globl  sys32_lseek_wrapper
-sys32_lseek_wrapper:
+ENTRY(sys32_lseek_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        lgfr    %r3,%r3                 # off_t
        llgfr   %r4,%r4                 # unsigned int
@@ -94,8 +82,7 @@ sys32_lseek_wrapper:
 
 #sys32_getpid_wrapper                          # void
 
-       .globl  sys32_mount_wrapper
-sys32_mount_wrapper:
+ENTRY(sys32_mount_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # char *
@@ -103,102 +90,85 @@ sys32_mount_wrapper:
        llgtr   %r6,%r6                 # void *
        jg      compat_sys_mount        # branch to system call
 
-       .globl  sys32_oldumount_wrapper
-sys32_oldumount_wrapper:
+ENTRY(sys32_oldumount_wrapper)
        llgtr   %r2,%r2                 # char *
        jg      sys_oldumount           # branch to system call
 
-       .globl  sys32_setuid16_wrapper
-sys32_setuid16_wrapper:
+ENTRY(sys32_setuid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
        jg      sys32_setuid16          # branch to system call
 
 #sys32_getuid16_wrapper                        # void
 
-       .globl  sys32_ptrace_wrapper
-sys32_ptrace_wrapper:
+ENTRY(sys32_ptrace_wrapper)
        lgfr    %r2,%r2                 # long
        lgfr    %r3,%r3                 # long
        llgtr   %r4,%r4                 # long
        llgfr   %r5,%r5                 # long
        jg      compat_sys_ptrace       # branch to system call
 
-       .globl  sys32_alarm_wrapper
-sys32_alarm_wrapper:
+ENTRY(sys32_alarm_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_alarm               # branch to system call
 
-       .globl  compat_sys_utime_wrapper
-compat_sys_utime_wrapper:
+ENTRY(compat_sys_utime_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct compat_utimbuf *
        jg      compat_sys_utime        # branch to system call
 
-       .globl  sys32_access_wrapper
-sys32_access_wrapper:
+ENTRY(sys32_access_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_access              # branch to system call
 
-       .globl  sys32_nice_wrapper
-sys32_nice_wrapper:
+ENTRY(sys32_nice_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_nice                # branch to system call
 
 #sys32_sync_wrapper                    # void
 
-       .globl  sys32_kill_wrapper
-sys32_kill_wrapper:
+ENTRY(sys32_kill_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_kill                # branch to system call
 
-       .globl  sys32_rename_wrapper
-sys32_rename_wrapper:
+ENTRY(sys32_rename_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_rename              # branch to system call
 
-       .globl  sys32_mkdir_wrapper
-sys32_mkdir_wrapper:
+ENTRY(sys32_mkdir_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_mkdir               # branch to system call
 
-       .globl  sys32_rmdir_wrapper
-sys32_rmdir_wrapper:
+ENTRY(sys32_rmdir_wrapper)
        llgtr   %r2,%r2                 # const char *
        jg      sys_rmdir               # branch to system call
 
-       .globl  sys32_dup_wrapper
-sys32_dup_wrapper:
+ENTRY(sys32_dup_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_dup                 # branch to system call
 
-       .globl  sys32_pipe_wrapper
-sys32_pipe_wrapper:
+ENTRY(sys32_pipe_wrapper)
        llgtr   %r2,%r2                 # u32 *
        jg      sys_pipe                # branch to system call
 
-       .globl  compat_sys_times_wrapper
-compat_sys_times_wrapper:
+ENTRY(compat_sys_times_wrapper)
        llgtr   %r2,%r2                 # struct compat_tms *
        jg      compat_sys_times        # branch to system call
 
-       .globl  sys32_brk_wrapper
-sys32_brk_wrapper:
+ENTRY(sys32_brk_wrapper)
        llgtr   %r2,%r2                 # unsigned long
        jg      sys_brk                 # branch to system call
 
-       .globl  sys32_setgid16_wrapper
-sys32_setgid16_wrapper:
+ENTRY(sys32_setgid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
        jg      sys32_setgid16          # branch to system call
 
 #sys32_getgid16_wrapper                        # void
 
-       .globl sys32_signal_wrapper
-sys32_signal_wrapper:
+ENTRY(sys32_signal_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # __sighandler_t
        jg      sys_signal
@@ -207,55 +177,46 @@ sys32_signal_wrapper:
 
 #sys32_getegid16_wrapper               # void
 
-       .globl  sys32_acct_wrapper
-sys32_acct_wrapper:
+ENTRY(sys32_acct_wrapper)
        llgtr   %r2,%r2                 # char *
        jg      sys_acct                # branch to system call
 
-       .globl  sys32_umount_wrapper
-sys32_umount_wrapper:
+ENTRY(sys32_umount_wrapper)
        llgtr   %r2,%r2                 # char *
        lgfr    %r3,%r3                 # int
        jg      sys_umount              # branch to system call
 
-       .globl  compat_sys_ioctl_wrapper
-compat_sys_ioctl_wrapper:
+ENTRY(compat_sys_ioctl_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        llgfr   %r4,%r4                 # unsigned int
        jg      compat_sys_ioctl        # branch to system call
 
-       .globl  compat_sys_fcntl_wrapper
-compat_sys_fcntl_wrapper:
+ENTRY(compat_sys_fcntl_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_fcntl        # branch to system call
 
-       .globl  sys32_setpgid_wrapper
-sys32_setpgid_wrapper:
+ENTRY(sys32_setpgid_wrapper)
        lgfr    %r2,%r2                 # pid_t
        lgfr    %r3,%r3                 # pid_t
        jg      sys_setpgid             # branch to system call
 
-       .globl  sys32_umask_wrapper
-sys32_umask_wrapper:
+ENTRY(sys32_umask_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_umask               # branch to system call
 
-       .globl  sys32_chroot_wrapper
-sys32_chroot_wrapper:
+ENTRY(sys32_chroot_wrapper)
        llgtr   %r2,%r2                 # char *
        jg      sys_chroot              # branch to system call
 
-       .globl sys32_ustat_wrapper
-sys32_ustat_wrapper:
+ENTRY(sys32_ustat_wrapper)
        llgfr   %r2,%r2                 # dev_t
        llgtr   %r3,%r3                 # struct ustat *
        jg      compat_sys_ustat
 
-       .globl  sys32_dup2_wrapper
-sys32_dup2_wrapper:
+ENTRY(sys32_dup2_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        jg      sys_dup2                # branch to system call
@@ -266,262 +227,220 @@ sys32_dup2_wrapper:
 
 #sys32_setsid_wrapper                  # void
 
-       .globl  sys32_sigaction_wrapper
-sys32_sigaction_wrapper:
+ENTRY(sys32_sigaction_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct old_sigaction *
        llgtr   %r4,%r4                 # struct old_sigaction32 *
        jg      sys32_sigaction         # branch to system call
 
-       .globl  sys32_setreuid16_wrapper
-sys32_setreuid16_wrapper:
+ENTRY(sys32_setreuid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
        llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
        jg      sys32_setreuid16        # branch to system call
 
-       .globl  sys32_setregid16_wrapper
-sys32_setregid16_wrapper:
+ENTRY(sys32_setregid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
        llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t
        jg      sys32_setregid16        # branch to system call
 
-       .globl sys_sigsuspend_wrapper
-sys_sigsuspend_wrapper:
+ENTRY(sys_sigsuspend_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        llgfr   %r4,%r4                 # old_sigset_t
        jg      sys_sigsuspend
 
-       .globl  compat_sys_sigpending_wrapper
-compat_sys_sigpending_wrapper:
+ENTRY(compat_sys_sigpending_wrapper)
        llgtr   %r2,%r2                 # compat_old_sigset_t *
        jg      compat_sys_sigpending   # branch to system call
 
-       .globl  sys32_sethostname_wrapper
-sys32_sethostname_wrapper:
+ENTRY(sys32_sethostname_wrapper)
        llgtr   %r2,%r2                 # char *
        lgfr    %r3,%r3                 # int
        jg      sys_sethostname         # branch to system call
 
-       .globl  compat_sys_setrlimit_wrapper
-compat_sys_setrlimit_wrapper:
+ENTRY(compat_sys_setrlimit_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct rlimit_emu31 *
        jg      compat_sys_setrlimit    # branch to system call
 
-       .globl  compat_sys_old_getrlimit_wrapper
-compat_sys_old_getrlimit_wrapper:
+ENTRY(compat_sys_old_getrlimit_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct rlimit_emu31 *
        jg      compat_sys_old_getrlimit # branch to system call
 
-       .globl  compat_sys_getrlimit_wrapper
-compat_sys_getrlimit_wrapper:
+ENTRY(compat_sys_getrlimit_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct rlimit_emu31 *
        jg      compat_sys_getrlimit    # branch to system call
 
-       .globl  sys32_mmap2_wrapper
-sys32_mmap2_wrapper:
+ENTRY(sys32_mmap2_wrapper)
        llgtr   %r2,%r2                 # struct mmap_arg_struct_emu31 *
        jg      sys32_mmap2                     # branch to system call
 
-       .globl  compat_sys_getrusage_wrapper
-compat_sys_getrusage_wrapper:
+ENTRY(compat_sys_getrusage_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct rusage_emu31 *
        jg      compat_sys_getrusage    # branch to system call
 
-       .globl  compat_sys_gettimeofday_wrapper
-compat_sys_gettimeofday_wrapper:
+ENTRY(compat_sys_gettimeofday_wrapper)
        llgtr   %r2,%r2                 # struct timeval_emu31 *
        llgtr   %r3,%r3                 # struct timezone *
        jg      compat_sys_gettimeofday # branch to system call
 
-       .globl  compat_sys_settimeofday_wrapper
-compat_sys_settimeofday_wrapper:
+ENTRY(compat_sys_settimeofday_wrapper)
        llgtr   %r2,%r2                 # struct timeval_emu31 *
        llgtr   %r3,%r3                 # struct timezone *
        jg      compat_sys_settimeofday # branch to system call
 
-       .globl  sys32_getgroups16_wrapper
-sys32_getgroups16_wrapper:
+ENTRY(sys32_getgroups16_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
        jg      sys32_getgroups16       # branch to system call
 
-       .globl  sys32_setgroups16_wrapper
-sys32_setgroups16_wrapper:
+ENTRY(sys32_setgroups16_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
        jg      sys32_setgroups16       # branch to system call
 
-       .globl  sys32_symlink_wrapper
-sys32_symlink_wrapper:
+ENTRY(sys32_symlink_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_symlink             # branch to system call
 
-       .globl  sys32_readlink_wrapper
-sys32_readlink_wrapper:
+ENTRY(sys32_readlink_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # char *
        lgfr    %r4,%r4                 # int
        jg      sys_readlink            # branch to system call
 
-       .globl  sys32_uselib_wrapper
-sys32_uselib_wrapper:
+ENTRY(sys32_uselib_wrapper)
        llgtr   %r2,%r2                 # const char *
        jg      sys_uselib              # branch to system call
 
-       .globl  sys32_swapon_wrapper
-sys32_swapon_wrapper:
+ENTRY(sys32_swapon_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        jg      sys_swapon              # branch to system call
 
-       .globl  sys32_reboot_wrapper
-sys32_reboot_wrapper:
+ENTRY(sys32_reboot_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        llgfr   %r4,%r4                 # unsigned int
        llgtr   %r5,%r5                 # void *
        jg      sys_reboot              # branch to system call
 
-       .globl  old32_readdir_wrapper
-old32_readdir_wrapper:
+ENTRY(old32_readdir_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # void *
        llgfr   %r4,%r4                 # unsigned int
        jg      compat_sys_old_readdir  # branch to system call
 
-       .globl  old32_mmap_wrapper
-old32_mmap_wrapper:
+ENTRY(old32_mmap_wrapper)
        llgtr   %r2,%r2                 # struct mmap_arg_struct_emu31 *
        jg      old32_mmap              # branch to system call
 
-       .globl  sys32_munmap_wrapper
-sys32_munmap_wrapper:
+ENTRY(sys32_munmap_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        jg      sys_munmap              # branch to system call
 
-       .globl  sys32_truncate_wrapper
-sys32_truncate_wrapper:
+ENTRY(sys32_truncate_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # long
        jg      sys_truncate            # branch to system call
 
-       .globl  sys32_ftruncate_wrapper
-sys32_ftruncate_wrapper:
+ENTRY(sys32_ftruncate_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned long
        jg      sys_ftruncate           # branch to system call
 
-       .globl  sys32_fchmod_wrapper
-sys32_fchmod_wrapper:
+ENTRY(sys32_fchmod_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # mode_t
        jg      sys_fchmod              # branch to system call
 
-       .globl  sys32_fchown16_wrapper
-sys32_fchown16_wrapper:
+ENTRY(sys32_fchown16_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # compat_uid_t
        llgfr   %r4,%r4                 # compat_uid_t
        jg      sys32_fchown16          # branch to system call
 
-       .globl  sys32_getpriority_wrapper
-sys32_getpriority_wrapper:
+ENTRY(sys32_getpriority_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_getpriority         # branch to system call
 
-       .globl  sys32_setpriority_wrapper
-sys32_setpriority_wrapper:
+ENTRY(sys32_setpriority_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
        jg      sys_setpriority         # branch to system call
 
-       .globl  compat_sys_statfs_wrapper
-compat_sys_statfs_wrapper:
+ENTRY(compat_sys_statfs_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct compat_statfs *
        jg      compat_sys_statfs       # branch to system call
 
-       .globl  compat_sys_fstatfs_wrapper
-compat_sys_fstatfs_wrapper:
+ENTRY(compat_sys_fstatfs_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct compat_statfs *
        jg      compat_sys_fstatfs      # branch to system call
 
-       .globl  compat_sys_socketcall_wrapper
-compat_sys_socketcall_wrapper:
+ENTRY(compat_sys_socketcall_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # u32 *
        jg      compat_sys_socketcall   # branch to system call
 
-       .globl  sys32_syslog_wrapper
-sys32_syslog_wrapper:
+ENTRY(sys32_syslog_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # char *
        lgfr    %r4,%r4                 # int
        jg      sys_syslog              # branch to system call
 
-       .globl  compat_sys_setitimer_wrapper
-compat_sys_setitimer_wrapper:
+ENTRY(compat_sys_setitimer_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct itimerval_emu31 *
        llgtr   %r4,%r4                 # struct itimerval_emu31 *
        jg      compat_sys_setitimer    # branch to system call
 
-       .globl  compat_sys_getitimer_wrapper
-compat_sys_getitimer_wrapper:
+ENTRY(compat_sys_getitimer_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct itimerval_emu31 *
        jg      compat_sys_getitimer    # branch to system call
 
-       .globl  compat_sys_newstat_wrapper
-compat_sys_newstat_wrapper:
+ENTRY(compat_sys_newstat_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct stat_emu31 *
        jg      compat_sys_newstat      # branch to system call
 
-       .globl  compat_sys_newlstat_wrapper
-compat_sys_newlstat_wrapper:
+ENTRY(compat_sys_newlstat_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct stat_emu31 *
        jg      compat_sys_newlstat     # branch to system call
 
-       .globl  compat_sys_newfstat_wrapper
-compat_sys_newfstat_wrapper:
+ENTRY(compat_sys_newfstat_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # struct stat_emu31 *
        jg      compat_sys_newfstat     # branch to system call
 
 #sys32_vhangup_wrapper                 # void
 
-       .globl  compat_sys_wait4_wrapper
-compat_sys_wait4_wrapper:
+ENTRY(compat_sys_wait4_wrapper)
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # unsigned int *
        lgfr    %r4,%r4                 # int
        llgtr   %r5,%r5                 # struct rusage *
        jg      compat_sys_wait4        # branch to system call
 
-       .globl  sys32_swapoff_wrapper
-sys32_swapoff_wrapper:
+ENTRY(sys32_swapoff_wrapper)
        llgtr   %r2,%r2                 # const char *
        jg      sys_swapoff             # branch to system call
 
-       .globl  compat_sys_sysinfo_wrapper
-compat_sys_sysinfo_wrapper:
+ENTRY(compat_sys_sysinfo_wrapper)
        llgtr   %r2,%r2                 # struct sysinfo_emu31 *
        jg      compat_sys_sysinfo      # branch to system call
 
-       .globl  sys32_ipc_wrapper
-sys32_ipc_wrapper:
+ENTRY(sys32_ipc_wrapper)
        llgfr   %r2,%r2                 # uint
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
@@ -529,8 +448,7 @@ sys32_ipc_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      sys32_ipc               # branch to system call
 
-       .globl  sys32_fsync_wrapper
-sys32_fsync_wrapper:
+ENTRY(sys32_fsync_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_fsync               # branch to system call
 
@@ -538,97 +456,81 @@ sys32_fsync_wrapper:
 
 #sys32_clone_wrapper                   # done in clone_glue
 
-       .globl  sys32_setdomainname_wrapper
-sys32_setdomainname_wrapper:
+ENTRY(sys32_setdomainname_wrapper)
        llgtr   %r2,%r2                 # char *
        lgfr    %r3,%r3                 # int
        jg      sys_setdomainname       # branch to system call
 
-       .globl  sys32_newuname_wrapper
-sys32_newuname_wrapper:
+ENTRY(sys32_newuname_wrapper)
        llgtr   %r2,%r2                 # struct new_utsname *
        jg      sys_newuname            # branch to system call
 
-       .globl  compat_sys_adjtimex_wrapper
-compat_sys_adjtimex_wrapper:
+ENTRY(compat_sys_adjtimex_wrapper)
        llgtr   %r2,%r2                 # struct compat_timex *
        jg      compat_sys_adjtimex     # branch to system call
 
-       .globl  sys32_mprotect_wrapper
-sys32_mprotect_wrapper:
+ENTRY(sys32_mprotect_wrapper)
        llgtr   %r2,%r2                 # unsigned long (actually pointer
        llgfr   %r3,%r3                 # size_t
        llgfr   %r4,%r4                 # unsigned long
        jg      sys_mprotect            # branch to system call
 
-       .globl  compat_sys_sigprocmask_wrapper
-compat_sys_sigprocmask_wrapper:
+ENTRY(compat_sys_sigprocmask_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_old_sigset_t *
        llgtr   %r4,%r4                 # compat_old_sigset_t *
        jg      compat_sys_sigprocmask          # branch to system call
 
-       .globl  sys_init_module_wrapper
-sys_init_module_wrapper:
+ENTRY(sys_init_module_wrapper)
        llgtr   %r2,%r2                 # void *
        llgfr   %r3,%r3                 # unsigned long
        llgtr   %r4,%r4                 # char *
        jg      sys_init_module         # branch to system call
 
-       .globl  sys_delete_module_wrapper
-sys_delete_module_wrapper:
+ENTRY(sys_delete_module_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # unsigned int
        jg      sys_delete_module       # branch to system call
 
-       .globl  sys32_quotactl_wrapper
-sys32_quotactl_wrapper:
+ENTRY(sys32_quotactl_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # qid_t
        llgtr   %r5,%r5                 # caddr_t
        jg      sys_quotactl            # branch to system call
 
-       .globl  sys32_getpgid_wrapper
-sys32_getpgid_wrapper:
+ENTRY(sys32_getpgid_wrapper)
        lgfr    %r2,%r2                 # pid_t
        jg      sys_getpgid             # branch to system call
 
-       .globl  sys32_fchdir_wrapper
-sys32_fchdir_wrapper:
+ENTRY(sys32_fchdir_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_fchdir              # branch to system call
 
-       .globl  sys32_bdflush_wrapper
-sys32_bdflush_wrapper:
+ENTRY(sys32_bdflush_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # long
        jg      sys_bdflush             # branch to system call
 
-       .globl  sys32_sysfs_wrapper
-sys32_sysfs_wrapper:
+ENTRY(sys32_sysfs_wrapper)
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
        jg      sys_sysfs               # branch to system call
 
-       .globl  sys32_personality_wrapper
-sys32_personality_wrapper:
+ENTRY(sys32_personality_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_s390_personality    # branch to system call
 
-       .globl  sys32_setfsuid16_wrapper
-sys32_setfsuid16_wrapper:
+ENTRY(sys32_setfsuid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
        jg      sys32_setfsuid16        # branch to system call
 
-       .globl  sys32_setfsgid16_wrapper
-sys32_setfsgid16_wrapper:
+ENTRY(sys32_setfsgid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
        jg      sys32_setfsgid16        # branch to system call
 
-       .globl  sys32_llseek_wrapper
-sys32_llseek_wrapper:
+ENTRY(sys32_llseek_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
@@ -636,15 +538,13 @@ sys32_llseek_wrapper:
        llgfr   %r6,%r6                 # unsigned int
        jg      sys_llseek              # branch to system call
 
-       .globl  sys32_getdents_wrapper
-sys32_getdents_wrapper:
+ENTRY(sys32_getdents_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # void *
        llgfr   %r4,%r4                 # unsigned int
        jg      compat_sys_getdents     # branch to system call
 
-       .globl  compat_sys_select_wrapper
-compat_sys_select_wrapper:
+ENTRY(compat_sys_select_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_fd_set *
        llgtr   %r4,%r4                 # compat_fd_set *
@@ -652,112 +552,94 @@ compat_sys_select_wrapper:
        llgtr   %r6,%r6                 # struct compat_timeval *
        jg      compat_sys_select       # branch to system call
 
-       .globl  sys32_flock_wrapper
-sys32_flock_wrapper:
+ENTRY(sys32_flock_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        jg      sys_flock               # branch to system call
 
-       .globl  sys32_msync_wrapper
-sys32_msync_wrapper:
+ENTRY(sys32_msync_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        lgfr    %r4,%r4                 # int
        jg      sys_msync               # branch to system call
 
-       .globl  compat_sys_readv_wrapper
-compat_sys_readv_wrapper:
+ENTRY(compat_sys_readv_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct compat_iovec *
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_readv        # branch to system call
 
-       .globl  compat_sys_writev_wrapper
-compat_sys_writev_wrapper:
+ENTRY(compat_sys_writev_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct compat_iovec *
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_writev       # branch to system call
 
-       .globl  sys32_getsid_wrapper
-sys32_getsid_wrapper:
+ENTRY(sys32_getsid_wrapper)
        lgfr    %r2,%r2                 # pid_t
        jg      sys_getsid              # branch to system call
 
-       .globl  sys32_fdatasync_wrapper
-sys32_fdatasync_wrapper:
+ENTRY(sys32_fdatasync_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_fdatasync           # branch to system call
 
-       .globl  sys32_mlock_wrapper
-sys32_mlock_wrapper:
+ENTRY(sys32_mlock_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        jg      sys_mlock               # branch to system call
 
-       .globl  sys32_munlock_wrapper
-sys32_munlock_wrapper:
+ENTRY(sys32_munlock_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        jg      sys_munlock             # branch to system call
 
-       .globl  sys32_mlockall_wrapper
-sys32_mlockall_wrapper:
+ENTRY(sys32_mlockall_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_mlockall            # branch to system call
 
 #sys32_munlockall_wrapper              # void
 
-       .globl  sys32_sched_setparam_wrapper
-sys32_sched_setparam_wrapper:
+ENTRY(sys32_sched_setparam_wrapper)
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # struct sched_param *
        jg      sys_sched_setparam      # branch to system call
 
-       .globl  sys32_sched_getparam_wrapper
-sys32_sched_getparam_wrapper:
+ENTRY(sys32_sched_getparam_wrapper)
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # struct sched_param *
        jg      sys_sched_getparam      # branch to system call
 
-       .globl  sys32_sched_setscheduler_wrapper
-sys32_sched_setscheduler_wrapper:
+ENTRY(sys32_sched_setscheduler_wrapper)
        lgfr    %r2,%r2                 # pid_t
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # struct sched_param *
        jg      sys_sched_setscheduler  # branch to system call
 
-       .globl  sys32_sched_getscheduler_wrapper
-sys32_sched_getscheduler_wrapper:
+ENTRY(sys32_sched_getscheduler_wrapper)
        lgfr    %r2,%r2                 # pid_t
        jg      sys_sched_getscheduler  # branch to system call
 
 #sys32_sched_yield_wrapper             # void
 
-       .globl  sys32_sched_get_priority_max_wrapper
-sys32_sched_get_priority_max_wrapper:
+ENTRY(sys32_sched_get_priority_max_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_sched_get_priority_max      # branch to system call
 
-       .globl  sys32_sched_get_priority_min_wrapper
-sys32_sched_get_priority_min_wrapper:
+ENTRY(sys32_sched_get_priority_min_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_sched_get_priority_min      # branch to system call
 
-       .globl  sys32_sched_rr_get_interval_wrapper
-sys32_sched_rr_get_interval_wrapper:
+ENTRY(sys32_sched_rr_get_interval_wrapper)
        lgfr    %r2,%r2                 # pid_t
        llgtr   %r3,%r3                 # struct compat_timespec *
        jg      sys32_sched_rr_get_interval     # branch to system call
 
-       .globl  compat_sys_nanosleep_wrapper
-compat_sys_nanosleep_wrapper:
+ENTRY(compat_sys_nanosleep_wrapper)
        llgtr   %r2,%r2                 # struct compat_timespec *
        llgtr   %r3,%r3                 # struct compat_timespec *
        jg      compat_sys_nanosleep            # branch to system call
 
-       .globl  sys32_mremap_wrapper
-sys32_mremap_wrapper:
+ENTRY(sys32_mremap_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
@@ -765,50 +647,43 @@ sys32_mremap_wrapper:
        llgfr   %r6,%r6                 # unsigned long
        jg      sys_mremap              # branch to system call
 
-       .globl  sys32_setresuid16_wrapper
-sys32_setresuid16_wrapper:
+ENTRY(sys32_setresuid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_uid_emu31_t
        llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
        llgfr   %r4,%r4                 # __kernel_old_uid_emu31_t
        jg      sys32_setresuid16       # branch to system call
 
-       .globl  sys32_getresuid16_wrapper
-sys32_getresuid16_wrapper:
+ENTRY(sys32_getresuid16_wrapper)
        llgtr   %r2,%r2                 # __kernel_old_uid_emu31_t *
        llgtr   %r3,%r3                 # __kernel_old_uid_emu31_t *
        llgtr   %r4,%r4                 # __kernel_old_uid_emu31_t *
        jg      sys32_getresuid16       # branch to system call
 
-       .globl  sys32_poll_wrapper
-sys32_poll_wrapper:
+ENTRY(sys32_poll_wrapper)
        llgtr   %r2,%r2                 # struct pollfd *
        llgfr   %r3,%r3                 # unsigned int
        lgfr    %r4,%r4                 # long
        jg      sys_poll                # branch to system call
 
-       .globl  compat_sys_nfsservctl_wrapper
-compat_sys_nfsservctl_wrapper:
+ENTRY(compat_sys_nfsservctl_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct compat_nfsctl_arg*
        llgtr   %r4,%r4                 # union compat_nfsctl_res*
        jg      compat_sys_nfsservctl   # branch to system call
 
-       .globl  sys32_setresgid16_wrapper
-sys32_setresgid16_wrapper:
+ENTRY(sys32_setresgid16_wrapper)
        llgfr   %r2,%r2                 # __kernel_old_gid_emu31_t
        llgfr   %r3,%r3                 # __kernel_old_gid_emu31_t
        llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t
        jg      sys32_setresgid16       # branch to system call
 
-       .globl  sys32_getresgid16_wrapper
-sys32_getresgid16_wrapper:
+ENTRY(sys32_getresgid16_wrapper)
        llgtr   %r2,%r2                 # __kernel_old_gid_emu31_t *
        llgtr   %r3,%r3                 # __kernel_old_gid_emu31_t *
        llgtr   %r4,%r4                 # __kernel_old_gid_emu31_t *
        jg      sys32_getresgid16       # branch to system call
 
-       .globl  sys32_prctl_wrapper
-sys32_prctl_wrapper:
+ENTRY(sys32_prctl_wrapper)
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
@@ -818,51 +693,44 @@ sys32_prctl_wrapper:
 
 #sys32_rt_sigreturn_wrapper            # done in rt_sigreturn_glue
 
-       .globl  sys32_rt_sigaction_wrapper
-sys32_rt_sigaction_wrapper:
+ENTRY(sys32_rt_sigaction_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const struct sigaction_emu31 *
        llgtr   %r4,%r4                 # const struct sigaction_emu31 *
        llgfr   %r5,%r5                 # size_t
        jg      sys32_rt_sigaction      # branch to system call
 
-       .globl  sys32_rt_sigprocmask_wrapper
-sys32_rt_sigprocmask_wrapper:
+ENTRY(sys32_rt_sigprocmask_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # old_sigset_emu31 *
        llgtr   %r4,%r4                 # old_sigset_emu31 *
        llgfr   %r5,%r5                 # size_t
        jg      sys32_rt_sigprocmask    # branch to system call
 
-       .globl  sys32_rt_sigpending_wrapper
-sys32_rt_sigpending_wrapper:
+ENTRY(sys32_rt_sigpending_wrapper)
        llgtr   %r2,%r2                 # sigset_emu31 *
        llgfr   %r3,%r3                 # size_t
        jg      sys32_rt_sigpending     # branch to system call
 
-       .globl  compat_sys_rt_sigtimedwait_wrapper
-compat_sys_rt_sigtimedwait_wrapper:
+ENTRY(compat_sys_rt_sigtimedwait_wrapper)
        llgtr   %r2,%r2                 # const sigset_emu31_t *
        llgtr   %r3,%r3                 # siginfo_emu31_t *
        llgtr   %r4,%r4                 # const struct compat_timespec *
        llgfr   %r5,%r5                 # size_t
        jg      compat_sys_rt_sigtimedwait      # branch to system call
 
-       .globl  sys32_rt_sigqueueinfo_wrapper
-sys32_rt_sigqueueinfo_wrapper:
+ENTRY(sys32_rt_sigqueueinfo_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # siginfo_emu31_t *
        jg      sys32_rt_sigqueueinfo   # branch to system call
 
-       .globl compat_sys_rt_sigsuspend_wrapper
-compat_sys_rt_sigsuspend_wrapper:
+ENTRY(compat_sys_rt_sigsuspend_wrapper)
        llgtr   %r2,%r2                 # compat_sigset_t *
        llgfr   %r3,%r3                 # compat_size_t
        jg      compat_sys_rt_sigsuspend
 
-       .globl  sys32_pread64_wrapper
-sys32_pread64_wrapper:
+ENTRY(sys32_pread64_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # char *
        llgfr   %r4,%r4                 # size_t
@@ -870,8 +738,7 @@ sys32_pread64_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      sys32_pread64           # branch to system call
 
-       .globl  sys32_pwrite64_wrapper
-sys32_pwrite64_wrapper:
+ENTRY(sys32_pwrite64_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # size_t
@@ -879,39 +746,33 @@ sys32_pwrite64_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      sys32_pwrite64          # branch to system call
 
-       .globl  sys32_chown16_wrapper
-sys32_chown16_wrapper:
+ENTRY(sys32_chown16_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # __kernel_old_uid_emu31_t
        llgfr   %r4,%r4                 # __kernel_old_gid_emu31_t
        jg      sys32_chown16           # branch to system call
 
-       .globl  sys32_getcwd_wrapper
-sys32_getcwd_wrapper:
+ENTRY(sys32_getcwd_wrapper)
        llgtr   %r2,%r2                 # char *
        llgfr   %r3,%r3                 # unsigned long
        jg      sys_getcwd              # branch to system call
 
-       .globl  sys32_capget_wrapper
-sys32_capget_wrapper:
+ENTRY(sys32_capget_wrapper)
        llgtr   %r2,%r2                 # cap_user_header_t
        llgtr   %r3,%r3                 # cap_user_data_t
        jg      sys_capget              # branch to system call
 
-       .globl  sys32_capset_wrapper
-sys32_capset_wrapper:
+ENTRY(sys32_capset_wrapper)
        llgtr   %r2,%r2                 # cap_user_header_t
        llgtr   %r3,%r3                 # const cap_user_data_t
        jg      sys_capset              # branch to system call
 
-       .globl sys32_sigaltstack_wrapper
-sys32_sigaltstack_wrapper:
+ENTRY(sys32_sigaltstack_wrapper)
        llgtr   %r2,%r2                 # const stack_emu31_t *
        llgtr   %r3,%r3                 # stack_emu31_t *
        jg      sys32_sigaltstack
 
-       .globl  sys32_sendfile_wrapper
-sys32_sendfile_wrapper:
+ENTRY(sys32_sendfile_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # __kernel_off_emu31_t *
@@ -920,22 +781,19 @@ sys32_sendfile_wrapper:
 
 #sys32_vfork_wrapper                   # done in vfork_glue
 
-       .globl  sys32_truncate64_wrapper
-sys32_truncate64_wrapper:
+ENTRY(sys32_truncate64_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
        jg      sys32_truncate64        # branch to system call
 
-       .globl  sys32_ftruncate64_wrapper
-sys32_ftruncate64_wrapper:
+ENTRY(sys32_ftruncate64_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
        jg      sys32_ftruncate64       # branch to system call
 
-       .globl sys32_lchown_wrapper
-sys32_lchown_wrapper:
+ENTRY(sys32_lchown_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # gid_t
@@ -946,156 +804,131 @@ sys32_lchown_wrapper:
 #sys32_geteuid_wrapper                 # void
 #sys32_getegid_wrapper                 # void
 
-       .globl sys32_setreuid_wrapper
-sys32_setreuid_wrapper:
+ENTRY(sys32_setreuid_wrapper)
        llgfr   %r2,%r2                 # uid_t
        llgfr   %r3,%r3                 # uid_t
        jg      sys_setreuid            # branch to system call
 
-       .globl sys32_setregid_wrapper
-sys32_setregid_wrapper:
+ENTRY(sys32_setregid_wrapper)
        llgfr   %r2,%r2                 # gid_t
        llgfr   %r3,%r3                 # gid_t
        jg      sys_setregid            # branch to system call
 
-       .globl  sys32_getgroups_wrapper
-sys32_getgroups_wrapper:
+ENTRY(sys32_getgroups_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # gid_t *
        jg      sys_getgroups           # branch to system call
 
-       .globl  sys32_setgroups_wrapper
-sys32_setgroups_wrapper:
+ENTRY(sys32_setgroups_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # gid_t *
        jg      sys_setgroups           # branch to system call
 
-       .globl sys32_fchown_wrapper
-sys32_fchown_wrapper:
+ENTRY(sys32_fchown_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # gid_t
        jg      sys_fchown              # branch to system call
 
-       .globl sys32_setresuid_wrapper
-sys32_setresuid_wrapper:
+ENTRY(sys32_setresuid_wrapper)
        llgfr   %r2,%r2                 # uid_t
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # uid_t
        jg      sys_setresuid           # branch to system call
 
-       .globl sys32_getresuid_wrapper
-sys32_getresuid_wrapper:
+ENTRY(sys32_getresuid_wrapper)
        llgtr   %r2,%r2                 # uid_t *
        llgtr   %r3,%r3                 # uid_t *
        llgtr   %r4,%r4                 # uid_t *
        jg      sys_getresuid           # branch to system call
 
-       .globl sys32_setresgid_wrapper
-sys32_setresgid_wrapper:
+ENTRY(sys32_setresgid_wrapper)
        llgfr   %r2,%r2                 # gid_t
        llgfr   %r3,%r3                 # gid_t
        llgfr   %r4,%r4                 # gid_t
        jg      sys_setresgid           # branch to system call
 
-       .globl sys32_getresgid_wrapper
-sys32_getresgid_wrapper:
+ENTRY(sys32_getresgid_wrapper)
        llgtr   %r2,%r2                 # gid_t *
        llgtr   %r3,%r3                 # gid_t *
        llgtr   %r4,%r4                 # gid_t *
        jg      sys_getresgid           # branch to system call
 
-       .globl sys32_chown_wrapper
-sys32_chown_wrapper:
+ENTRY(sys32_chown_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # uid_t
        llgfr   %r4,%r4                 # gid_t
        jg      sys_chown               # branch to system call
 
-       .globl sys32_setuid_wrapper
-sys32_setuid_wrapper:
+ENTRY(sys32_setuid_wrapper)
        llgfr   %r2,%r2                 # uid_t
        jg      sys_setuid              # branch to system call
 
-       .globl sys32_setgid_wrapper
-sys32_setgid_wrapper:
+ENTRY(sys32_setgid_wrapper)
        llgfr   %r2,%r2                 # gid_t
        jg      sys_setgid              # branch to system call
 
-       .globl sys32_setfsuid_wrapper
-sys32_setfsuid_wrapper:
+ENTRY(sys32_setfsuid_wrapper)
        llgfr   %r2,%r2                 # uid_t
        jg      sys_setfsuid            # branch to system call
 
-       .globl sys32_setfsgid_wrapper
-sys32_setfsgid_wrapper:
+ENTRY(sys32_setfsgid_wrapper)
        llgfr   %r2,%r2                 # gid_t
        jg      sys_setfsgid            # branch to system call
 
-       .globl  sys32_pivot_root_wrapper
-sys32_pivot_root_wrapper:
+ENTRY(sys32_pivot_root_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        jg      sys_pivot_root          # branch to system call
 
-       .globl  sys32_mincore_wrapper
-sys32_mincore_wrapper:
+ENTRY(sys32_mincore_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        llgtr   %r4,%r4                 # unsigned char *
        jg      sys_mincore             # branch to system call
 
-       .globl  sys32_madvise_wrapper
-sys32_madvise_wrapper:
+ENTRY(sys32_madvise_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # size_t
        lgfr    %r4,%r4                 # int
        jg      sys_madvise             # branch to system call
 
-       .globl  sys32_getdents64_wrapper
-sys32_getdents64_wrapper:
+ENTRY(sys32_getdents64_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # void *
        llgfr   %r4,%r4                 # unsigned int
        jg      sys_getdents64          # branch to system call
 
-       .globl  compat_sys_fcntl64_wrapper
-compat_sys_fcntl64_wrapper:
+ENTRY(compat_sys_fcntl64_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        llgfr   %r4,%r4                 # unsigned long
        jg      compat_sys_fcntl64      # branch to system call
 
-       .globl  sys32_stat64_wrapper
-sys32_stat64_wrapper:
+ENTRY(sys32_stat64_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct stat64 *
        jg      sys32_stat64            # branch to system call
 
-       .globl  sys32_lstat64_wrapper
-sys32_lstat64_wrapper:
+ENTRY(sys32_lstat64_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct stat64 *
        jg      sys32_lstat64           # branch to system call
 
-       .globl  sys32_stime_wrapper
-sys32_stime_wrapper:
+ENTRY(sys32_stime_wrapper)
        llgtr   %r2,%r2                 # long *
        jg      compat_sys_stime        # branch to system call
 
-       .globl  sys32_sysctl_wrapper
-sys32_sysctl_wrapper:
+ENTRY(sys32_sysctl_wrapper)
        llgtr   %r2,%r2                 # struct compat_sysctl_args *
        jg      compat_sys_sysctl
 
-       .globl  sys32_fstat64_wrapper
-sys32_fstat64_wrapper:
+ENTRY(sys32_fstat64_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgtr   %r3,%r3                 # struct stat64 *
        jg      sys32_fstat64           # branch to system call
 
-       .globl  compat_sys_futex_wrapper
-compat_sys_futex_wrapper:
+ENTRY(compat_sys_futex_wrapper)
        llgtr   %r2,%r2                 # u32 *
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
@@ -1105,8 +938,7 @@ compat_sys_futex_wrapper:
        stg     %r0,160(%r15)
        jg      compat_sys_futex        # branch to system call
 
-       .globl  sys32_setxattr_wrapper
-sys32_setxattr_wrapper:
+ENTRY(sys32_setxattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # void *
@@ -1114,8 +946,7 @@ sys32_setxattr_wrapper:
        lgfr    %r6,%r6                 # int
        jg      sys_setxattr
 
-       .globl  sys32_lsetxattr_wrapper
-sys32_lsetxattr_wrapper:
+ENTRY(sys32_lsetxattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # void *
@@ -1123,8 +954,7 @@ sys32_lsetxattr_wrapper:
        lgfr    %r6,%r6                 # int
        jg      sys_lsetxattr
 
-       .globl  sys32_fsetxattr_wrapper
-sys32_fsetxattr_wrapper:
+ENTRY(sys32_fsetxattr_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # void *
@@ -1132,124 +962,106 @@ sys32_fsetxattr_wrapper:
        lgfr    %r6,%r6                 # int
        jg      sys_fsetxattr
 
-       .globl  sys32_getxattr_wrapper
-sys32_getxattr_wrapper:
+ENTRY(sys32_getxattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # void *
        llgfr   %r5,%r5                 # size_t
        jg      sys_getxattr
 
-       .globl  sys32_lgetxattr_wrapper
-sys32_lgetxattr_wrapper:
+ENTRY(sys32_lgetxattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # void *
        llgfr   %r5,%r5                 # size_t
        jg      sys_lgetxattr
 
-       .globl  sys32_fgetxattr_wrapper
-sys32_fgetxattr_wrapper:
+ENTRY(sys32_fgetxattr_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # void *
        llgfr   %r5,%r5                 # size_t
        jg      sys_fgetxattr
 
-       .globl  sys32_listxattr_wrapper
-sys32_listxattr_wrapper:
+ENTRY(sys32_listxattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        llgfr   %r4,%r4                 # size_t
        jg      sys_listxattr
 
-       .globl  sys32_llistxattr_wrapper
-sys32_llistxattr_wrapper:
+ENTRY(sys32_llistxattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        llgfr   %r4,%r4                 # size_t
        jg      sys_llistxattr
 
-       .globl  sys32_flistxattr_wrapper
-sys32_flistxattr_wrapper:
+ENTRY(sys32_flistxattr_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # char *
        llgfr   %r4,%r4                 # size_t
        jg      sys_flistxattr
 
-       .globl  sys32_removexattr_wrapper
-sys32_removexattr_wrapper:
+ENTRY(sys32_removexattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        jg      sys_removexattr
 
-       .globl  sys32_lremovexattr_wrapper
-sys32_lremovexattr_wrapper:
+ENTRY(sys32_lremovexattr_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # char *
        jg      sys_lremovexattr
 
-       .globl  sys32_fremovexattr_wrapper
-sys32_fremovexattr_wrapper:
+ENTRY(sys32_fremovexattr_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # char *
        jg      sys_fremovexattr
 
-       .globl  sys32_sched_setaffinity_wrapper
-sys32_sched_setaffinity_wrapper:
+ENTRY(sys32_sched_setaffinity_wrapper)
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # unsigned int
        llgtr   %r4,%r4                 # unsigned long *
        jg      compat_sys_sched_setaffinity
 
-       .globl  sys32_sched_getaffinity_wrapper
-sys32_sched_getaffinity_wrapper:
+ENTRY(sys32_sched_getaffinity_wrapper)
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # unsigned int
        llgtr   %r4,%r4                 # unsigned long *
        jg      compat_sys_sched_getaffinity
 
-       .globl  sys32_exit_group_wrapper
-sys32_exit_group_wrapper:
+ENTRY(sys32_exit_group_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_exit_group          # branch to system call
 
-       .globl  sys32_set_tid_address_wrapper
-sys32_set_tid_address_wrapper:
+ENTRY(sys32_set_tid_address_wrapper)
        llgtr   %r2,%r2                 # int *
        jg      sys_set_tid_address     # branch to system call
 
-       .globl  sys_epoll_create_wrapper
-sys_epoll_create_wrapper:
+ENTRY(sys_epoll_create_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_epoll_create        # branch to system call
 
-       .globl  sys_epoll_ctl_wrapper
-sys_epoll_ctl_wrapper:
+ENTRY(sys_epoll_ctl_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
        llgtr   %r5,%r5                 # struct epoll_event *
        jg      sys_epoll_ctl           # branch to system call
 
-       .globl  sys_epoll_wait_wrapper
-sys_epoll_wait_wrapper:
+ENTRY(sys_epoll_wait_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct epoll_event *
        lgfr    %r4,%r4                 # int
        lgfr    %r5,%r5                 # int
        jg      sys_epoll_wait          # branch to system call
 
-       .globl  sys32_lookup_dcookie_wrapper
-sys32_lookup_dcookie_wrapper:
+ENTRY(sys32_lookup_dcookie_wrapper)
        sllg    %r2,%r2,32              # get high word of 64bit dcookie
        or      %r2,%r3                 # get low word of 64bit dcookie
        llgtr   %r3,%r4                 # char *
        llgfr   %r4,%r5                 # size_t
        jg      sys_lookup_dcookie
 
-       .globl  sys32_fadvise64_wrapper
-sys32_fadvise64_wrapper:
+ENTRY(sys32_fadvise64_wrapper)
        lgfr    %r2,%r2                 # int
        sllg    %r3,%r3,32              # get high word of 64bit loff_t
        or      %r3,%r4                 # get low word of 64bit loff_t
@@ -1257,81 +1069,68 @@ sys32_fadvise64_wrapper:
        lgfr    %r5,%r6                 # int
        jg      sys32_fadvise64
 
-       .globl  sys32_fadvise64_64_wrapper
-sys32_fadvise64_64_wrapper:
+ENTRY(sys32_fadvise64_64_wrapper)
        llgtr   %r2,%r2                 # struct fadvise64_64_args *
        jg      sys32_fadvise64_64
 
-       .globl  sys32_clock_settime_wrapper
-sys32_clock_settime_wrapper:
+ENTRY(sys32_clock_settime_wrapper)
        lgfr    %r2,%r2                 # clockid_t (int)
        llgtr   %r3,%r3                 # struct compat_timespec *
        jg      compat_sys_clock_settime
 
-       .globl  sys32_clock_gettime_wrapper
-sys32_clock_gettime_wrapper:
+ENTRY(sys32_clock_gettime_wrapper)
        lgfr    %r2,%r2                 # clockid_t (int)
        llgtr   %r3,%r3                 # struct compat_timespec *
        jg      compat_sys_clock_gettime
 
-       .globl  sys32_clock_getres_wrapper
-sys32_clock_getres_wrapper:
+ENTRY(sys32_clock_getres_wrapper)
        lgfr    %r2,%r2                 # clockid_t (int)
        llgtr   %r3,%r3                 # struct compat_timespec *
        jg      compat_sys_clock_getres
 
-       .globl  sys32_clock_nanosleep_wrapper
-sys32_clock_nanosleep_wrapper:
+ENTRY(sys32_clock_nanosleep_wrapper)
        lgfr    %r2,%r2                 # clockid_t (int)
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # struct compat_timespec *
        llgtr   %r5,%r5                 # struct compat_timespec *
        jg      compat_sys_clock_nanosleep
 
-       .globl  sys32_timer_create_wrapper
-sys32_timer_create_wrapper:
+ENTRY(sys32_timer_create_wrapper)
        lgfr    %r2,%r2                 # timer_t (int)
        llgtr   %r3,%r3                 # struct compat_sigevent *
        llgtr   %r4,%r4                 # timer_t *
        jg      compat_sys_timer_create
 
-       .globl  sys32_timer_settime_wrapper
-sys32_timer_settime_wrapper:
+ENTRY(sys32_timer_settime_wrapper)
        lgfr    %r2,%r2                 # timer_t (int)
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # struct compat_itimerspec *
        llgtr   %r5,%r5                 # struct compat_itimerspec *
        jg      compat_sys_timer_settime
 
-       .globl  sys32_timer_gettime_wrapper
-sys32_timer_gettime_wrapper:
+ENTRY(sys32_timer_gettime_wrapper)
        lgfr    %r2,%r2                 # timer_t (int)
        llgtr   %r3,%r3                 # struct compat_itimerspec *
        jg      compat_sys_timer_gettime
 
-       .globl  sys32_timer_getoverrun_wrapper
-sys32_timer_getoverrun_wrapper:
+ENTRY(sys32_timer_getoverrun_wrapper)
        lgfr    %r2,%r2                 # timer_t (int)
        jg      sys_timer_getoverrun
 
-       .globl  sys32_timer_delete_wrapper
-sys32_timer_delete_wrapper:
+ENTRY(sys32_timer_delete_wrapper)
        lgfr    %r2,%r2                 # timer_t (int)
        jg      sys_timer_delete
 
-       .globl  sys32_io_setup_wrapper
-sys32_io_setup_wrapper:
+ENTRY(sys32_io_setup_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # u32 *
        jg      compat_sys_io_setup
 
-       .globl  sys32_io_destroy_wrapper
-sys32_io_destroy_wrapper:
+ENTRY(sys32_io_destroy_wrapper)
        llgfr   %r2,%r2                 # (aio_context_t) u32
        jg      sys_io_destroy
 
-       .globl  sys32_io_getevents_wrapper
-sys32_io_getevents_wrapper:
+ENTRY(sys32_io_getevents_wrapper)
        llgfr   %r2,%r2                 # (aio_context_t) u32
        lgfr    %r3,%r3                 # long
        lgfr    %r4,%r4                 # long
@@ -1339,49 +1138,42 @@ sys32_io_getevents_wrapper:
        llgtr   %r6,%r6                 # struct compat_timespec *
        jg      compat_sys_io_getevents
 
-       .globl  sys32_io_submit_wrapper
-sys32_io_submit_wrapper:
+ENTRY(sys32_io_submit_wrapper)
        llgfr   %r2,%r2                 # (aio_context_t) u32
        lgfr    %r3,%r3                 # long
        llgtr   %r4,%r4                 # struct iocb **
        jg      compat_sys_io_submit
 
-       .globl  sys32_io_cancel_wrapper
-sys32_io_cancel_wrapper:
+ENTRY(sys32_io_cancel_wrapper)
        llgfr   %r2,%r2                 # (aio_context_t) u32
        llgtr   %r3,%r3                 # struct iocb *
        llgtr   %r4,%r4                 # struct io_event *
        jg      sys_io_cancel
 
-       .globl compat_sys_statfs64_wrapper
-compat_sys_statfs64_wrapper:
+ENTRY(compat_sys_statfs64_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgfr   %r3,%r3                 # compat_size_t
        llgtr   %r4,%r4                 # struct compat_statfs64 *
        jg      compat_sys_statfs64
 
-       .globl compat_sys_fstatfs64_wrapper
-compat_sys_fstatfs64_wrapper:
+ENTRY(compat_sys_fstatfs64_wrapper)
        llgfr   %r2,%r2                 # unsigned int fd
        llgfr   %r3,%r3                 # compat_size_t
        llgtr   %r4,%r4                 # struct compat_statfs64 *
        jg      compat_sys_fstatfs64
 
-       .globl  compat_sys_mq_open_wrapper
-compat_sys_mq_open_wrapper:
+ENTRY(compat_sys_mq_open_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        llgfr   %r4,%r4                 # mode_t
        llgtr   %r5,%r5                 # struct compat_mq_attr *
        jg      compat_sys_mq_open
 
-       .globl  sys32_mq_unlink_wrapper
-sys32_mq_unlink_wrapper:
+ENTRY(sys32_mq_unlink_wrapper)
        llgtr   %r2,%r2                 # const char *
        jg      sys_mq_unlink
 
-       .globl  compat_sys_mq_timedsend_wrapper
-compat_sys_mq_timedsend_wrapper:
+ENTRY(compat_sys_mq_timedsend_wrapper)
        lgfr    %r2,%r2                 # mqd_t
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # size_t
@@ -1389,8 +1181,7 @@ compat_sys_mq_timedsend_wrapper:
        llgtr   %r6,%r6                 # const struct compat_timespec *
        jg      compat_sys_mq_timedsend
 
-       .globl  compat_sys_mq_timedreceive_wrapper
-compat_sys_mq_timedreceive_wrapper:
+ENTRY(compat_sys_mq_timedreceive_wrapper)
        lgfr    %r2,%r2                 # mqd_t
        llgtr   %r3,%r3                 # char *
        llgfr   %r4,%r4                 # size_t
@@ -1398,21 +1189,18 @@ compat_sys_mq_timedreceive_wrapper:
        llgtr   %r6,%r6                 # const struct compat_timespec *
        jg      compat_sys_mq_timedreceive
 
-       .globl  compat_sys_mq_notify_wrapper
-compat_sys_mq_notify_wrapper:
+ENTRY(compat_sys_mq_notify_wrapper)
        lgfr    %r2,%r2                 # mqd_t
        llgtr   %r3,%r3                 # struct compat_sigevent *
        jg      compat_sys_mq_notify
 
-       .globl  compat_sys_mq_getsetattr_wrapper
-compat_sys_mq_getsetattr_wrapper:
+ENTRY(compat_sys_mq_getsetattr_wrapper)
        lgfr    %r2,%r2                 # mqd_t
        llgtr   %r3,%r3                 # struct compat_mq_attr *
        llgtr   %r4,%r4                 # struct compat_mq_attr *
        jg      compat_sys_mq_getsetattr
 
-       .globl  compat_sys_add_key_wrapper
-compat_sys_add_key_wrapper:
+ENTRY(compat_sys_add_key_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        llgtr   %r4,%r4                 # const void *
@@ -1420,16 +1208,14 @@ compat_sys_add_key_wrapper:
        llgfr   %r6,%r6                 # (key_serial_t) u32
        jg      sys_add_key
 
-       .globl  compat_sys_request_key_wrapper
-compat_sys_request_key_wrapper:
+ENTRY(compat_sys_request_key_wrapper)
        llgtr   %r2,%r2                 # const char *
        llgtr   %r3,%r3                 # const char *
        llgtr   %r4,%r4                 # const void *
        llgfr   %r5,%r5                 # (key_serial_t) u32
        jg      sys_request_key
 
-       .globl  sys32_remap_file_pages_wrapper
-sys32_remap_file_pages_wrapper:
+ENTRY(sys32_remap_file_pages_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # unsigned long
        llgfr   %r4,%r4                 # unsigned long
@@ -1437,8 +1223,7 @@ sys32_remap_file_pages_wrapper:
        llgfr   %r6,%r6                 # unsigned long
        jg      sys_remap_file_pages
 
-       .globl  compat_sys_waitid_wrapper
-compat_sys_waitid_wrapper:
+ENTRY(compat_sys_waitid_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # pid_t
        llgtr   %r4,%r4                 # siginfo_emu31_t *
@@ -1446,65 +1231,56 @@ compat_sys_waitid_wrapper:
        llgtr   %r6,%r6                 # struct rusage_emu31 *
        jg      compat_sys_waitid
 
-       .globl  compat_sys_kexec_load_wrapper
-compat_sys_kexec_load_wrapper:
+ENTRY(compat_sys_kexec_load_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # unsigned long
        llgtr   %r4,%r4                 # struct kexec_segment *
        llgfr   %r5,%r5                 # unsigned long
        jg      compat_sys_kexec_load
 
-       .globl  sys_ioprio_set_wrapper
-sys_ioprio_set_wrapper:
+ENTRY(sys_ioprio_set_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
        jg      sys_ioprio_set
 
-       .globl  sys_ioprio_get_wrapper
-sys_ioprio_get_wrapper:
+ENTRY(sys_ioprio_get_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_ioprio_get
 
-       .globl  sys_inotify_add_watch_wrapper
-sys_inotify_add_watch_wrapper:
+ENTRY(sys_inotify_add_watch_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # u32
        jg      sys_inotify_add_watch
 
-       .globl  sys_inotify_rm_watch_wrapper
-sys_inotify_rm_watch_wrapper:
+ENTRY(sys_inotify_rm_watch_wrapper)
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # u32
        jg      sys_inotify_rm_watch
 
-       .globl compat_sys_openat_wrapper
-compat_sys_openat_wrapper:
+ENTRY(compat_sys_openat_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # const char *
        lgfr    %r4,%r4                 # int
        lgfr    %r5,%r5                 # int
        jg      compat_sys_openat
 
-       .globl sys_mkdirat_wrapper
-sys_mkdirat_wrapper:
+ENTRY(sys_mkdirat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        lgfr    %r4,%r4                 # int
        jg      sys_mkdirat
 
-       .globl sys_mknodat_wrapper
-sys_mknodat_wrapper:
+ENTRY(sys_mknodat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        lgfr    %r4,%r4                 # int
        llgfr   %r5,%r5                 # unsigned int
        jg      sys_mknodat
 
-       .globl sys_fchownat_wrapper
-sys_fchownat_wrapper:
+ENTRY(sys_fchownat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # uid_t
@@ -1512,38 +1288,33 @@ sys_fchownat_wrapper:
        lgfr    %r6,%r6                 # int
        jg      sys_fchownat
 
-       .globl compat_sys_futimesat_wrapper
-compat_sys_futimesat_wrapper:
+ENTRY(compat_sys_futimesat_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # struct timeval *
        jg      compat_sys_futimesat
 
-       .globl sys32_fstatat64_wrapper
-sys32_fstatat64_wrapper:
+ENTRY(sys32_fstatat64_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # struct stat64 *
        lgfr    %r5,%r5                 # int
        jg      sys32_fstatat64
 
-       .globl sys_unlinkat_wrapper
-sys_unlinkat_wrapper:
+ENTRY(sys_unlinkat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        lgfr    %r4,%r4                 # int
        jg      sys_unlinkat
 
-       .globl sys_renameat_wrapper
-sys_renameat_wrapper:
+ENTRY(sys_renameat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        lgfr    %r4,%r4                 # int
        llgtr   %r5,%r5                 # const char *
        jg      sys_renameat
 
-       .globl sys_linkat_wrapper
-sys_linkat_wrapper:
+ENTRY(sys_linkat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        lgfr    %r4,%r4                 # int
@@ -1551,37 +1322,32 @@ sys_linkat_wrapper:
        lgfr    %r6,%r6                 # int
        jg      sys_linkat
 
-       .globl sys_symlinkat_wrapper
-sys_symlinkat_wrapper:
+ENTRY(sys_symlinkat_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # const char *
        jg      sys_symlinkat
 
-       .globl sys_readlinkat_wrapper
-sys_readlinkat_wrapper:
+ENTRY(sys_readlinkat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        llgtr   %r4,%r4                 # char *
        lgfr    %r5,%r5                 # int
        jg      sys_readlinkat
 
-       .globl sys_fchmodat_wrapper
-sys_fchmodat_wrapper:
+ENTRY(sys_fchmodat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        llgfr   %r4,%r4                 # mode_t
        jg      sys_fchmodat
 
-       .globl sys_faccessat_wrapper
-sys_faccessat_wrapper:
+ENTRY(sys_faccessat_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char *
        lgfr    %r4,%r4                 # int
        jg      sys_faccessat
 
-       .globl compat_sys_pselect6_wrapper
-compat_sys_pselect6_wrapper:
+ENTRY(compat_sys_pselect6_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # fd_set *
        llgtr   %r4,%r4                 # fd_set *
@@ -1591,8 +1357,7 @@ compat_sys_pselect6_wrapper:
        stg     %r0,160(%r15)
        jg      compat_sys_pselect6
 
-       .globl compat_sys_ppoll_wrapper
-compat_sys_ppoll_wrapper:
+ENTRY(compat_sys_ppoll_wrapper)
        llgtr   %r2,%r2                 # struct pollfd *
        llgfr   %r3,%r3                 # unsigned int
        llgtr   %r4,%r4                 # struct timespec *
@@ -1600,26 +1365,22 @@ compat_sys_ppoll_wrapper:
        llgfr   %r6,%r6                 # size_t
        jg      compat_sys_ppoll
 
-       .globl sys_unshare_wrapper
-sys_unshare_wrapper:
+ENTRY(sys_unshare_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        jg      sys_unshare
 
-       .globl compat_sys_set_robust_list_wrapper
-compat_sys_set_robust_list_wrapper:
+ENTRY(compat_sys_set_robust_list_wrapper)
        llgtr   %r2,%r2                 # struct compat_robust_list_head *
        llgfr   %r3,%r3                 # size_t
        jg      compat_sys_set_robust_list
 
-       .globl compat_sys_get_robust_list_wrapper
-compat_sys_get_robust_list_wrapper:
+ENTRY(compat_sys_get_robust_list_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_uptr_t_t *
        llgtr   %r4,%r4                 # compat_size_t *
        jg      compat_sys_get_robust_list
 
-       .globl sys_splice_wrapper
-sys_splice_wrapper:
+ENTRY(sys_splice_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # loff_t *
        lgfr    %r4,%r4                 # int
@@ -1629,8 +1390,7 @@ sys_splice_wrapper:
        stg     %r0,160(%r15)
        jg      sys_splice
 
-       .globl  sys_sync_file_range_wrapper
-sys_sync_file_range_wrapper:
+ENTRY(sys_sync_file_range_wrapper)
        lgfr    %r2,%r2                 # int
        sllg    %r3,%r3,32              # get high word of 64bit loff_t
        or      %r3,%r4                 # get low word of 64bit loff_t
@@ -1639,31 +1399,27 @@ sys_sync_file_range_wrapper:
        llgf    %r5,164(%r15)           # unsigned int
        jg      sys_sync_file_range
 
-       .globl  sys_tee_wrapper
-sys_tee_wrapper:
+ENTRY(sys_tee_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        llgfr   %r4,%r4                 # size_t
        llgfr   %r5,%r5                 # unsigned int
        jg      sys_tee
 
-       .globl compat_sys_vmsplice_wrapper
-compat_sys_vmsplice_wrapper:
+ENTRY(compat_sys_vmsplice_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_iovec *
        llgfr   %r4,%r4                 # unsigned int
        llgfr   %r5,%r5                 # unsigned int
        jg      compat_sys_vmsplice
 
-       .globl  sys_getcpu_wrapper
-sys_getcpu_wrapper:
+ENTRY(sys_getcpu_wrapper)
        llgtr   %r2,%r2                 # unsigned *
        llgtr   %r3,%r3                 # unsigned *
        llgtr   %r4,%r4                 # struct getcpu_cache *
        jg      sys_getcpu
 
-       .globl  compat_sys_epoll_pwait_wrapper
-compat_sys_epoll_pwait_wrapper:
+ENTRY(compat_sys_epoll_pwait_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct compat_epoll_event *
        lgfr    %r4,%r4                 # int
@@ -1673,34 +1429,29 @@ compat_sys_epoll_pwait_wrapper:
        stg     %r0,160(%r15)
        jg      compat_sys_epoll_pwait
 
-       .globl  compat_sys_utimes_wrapper
-compat_sys_utimes_wrapper:
+ENTRY(compat_sys_utimes_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # struct compat_timeval *
        jg      compat_sys_utimes
 
-       .globl  compat_sys_utimensat_wrapper
-compat_sys_utimensat_wrapper:
+ENTRY(compat_sys_utimensat_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgtr   %r3,%r3                 # char *
        llgtr   %r4,%r4                 # struct compat_timespec *
        lgfr    %r5,%r5                 # int
        jg      compat_sys_utimensat
 
-       .globl  compat_sys_signalfd_wrapper
-compat_sys_signalfd_wrapper:
+ENTRY(compat_sys_signalfd_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_sigset_t *
        llgfr   %r4,%r4                 # compat_size_t
        jg      compat_sys_signalfd
 
-       .globl  sys_eventfd_wrapper
-sys_eventfd_wrapper:
+ENTRY(sys_eventfd_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        jg      sys_eventfd
 
-       .globl  sys_fallocate_wrapper
-sys_fallocate_wrapper:
+ENTRY(sys_fallocate_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        sllg    %r4,%r4,32              # get high word of 64bit loff_t
@@ -1709,94 +1460,80 @@ sys_fallocate_wrapper:
        l       %r5,164(%r15)           # get low word of 64bit loff_t
        jg      sys_fallocate
 
-       .globl  sys_timerfd_create_wrapper
-sys_timerfd_create_wrapper:
+ENTRY(sys_timerfd_create_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_timerfd_create
 
-       .globl  compat_sys_timerfd_settime_wrapper
-compat_sys_timerfd_settime_wrapper:
+ENTRY(compat_sys_timerfd_settime_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # struct compat_itimerspec *
        llgtr   %r5,%r5                 # struct compat_itimerspec *
        jg      compat_sys_timerfd_settime
 
-       .globl  compat_sys_timerfd_gettime_wrapper
-compat_sys_timerfd_gettime_wrapper:
+ENTRY(compat_sys_timerfd_gettime_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct compat_itimerspec *
        jg      compat_sys_timerfd_gettime
 
-       .globl compat_sys_signalfd4_wrapper
-compat_sys_signalfd4_wrapper:
+ENTRY(compat_sys_signalfd4_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # compat_sigset_t *
        llgfr   %r4,%r4                 # compat_size_t
        lgfr    %r5,%r5                 # int
        jg      compat_sys_signalfd4
 
-       .globl sys_eventfd2_wrapper
-sys_eventfd2_wrapper:
+ENTRY(sys_eventfd2_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        lgfr    %r3,%r3                 # int
        jg      sys_eventfd2
 
-       .globl  sys_inotify_init1_wrapper
-sys_inotify_init1_wrapper:
+ENTRY(sys_inotify_init1_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_inotify_init1
 
-       .globl  sys_pipe2_wrapper
-sys_pipe2_wrapper:
+ENTRY(sys_pipe2_wrapper)
        llgtr   %r2,%r2                 # u32 *
        lgfr    %r3,%r3                 # int
        jg      sys_pipe2               # branch to system call
 
-       .globl  sys_dup3_wrapper
-sys_dup3_wrapper:
+ENTRY(sys_dup3_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        lgfr    %r4,%r4                 # int
        jg      sys_dup3                # branch to system call
 
-       .globl  sys_epoll_create1_wrapper
-sys_epoll_create1_wrapper:
+ENTRY(sys_epoll_create1_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_epoll_create1       # branch to system call
 
-       .globl  sys32_readahead_wrapper
-sys32_readahead_wrapper:
+ENTRY(sys32_readahead_wrapper)
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # u32
        llgfr   %r4,%r4                 # u32
        lgfr    %r5,%r5                 # s32
        jg      sys32_readahead         # branch to system call
 
-       .globl  sys32_sendfile64_wrapper
-sys32_sendfile64_wrapper:
+ENTRY(sys32_sendfile64_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        llgtr   %r4,%r4                 # compat_loff_t *
        lgfr    %r5,%r5                 # s32
        jg      sys32_sendfile64        # branch to system call
 
-       .globl  sys_tkill_wrapper
-sys_tkill_wrapper:
+ENTRY(sys_tkill_wrapper)
        lgfr    %r2,%r2                 # pid_t
        lgfr    %r3,%r3                 # int
        jg      sys_tkill               # branch to system call
 
-       .globl  sys_tgkill_wrapper
-sys_tgkill_wrapper:
+ENTRY(sys_tgkill_wrapper)
        lgfr    %r2,%r2                 # pid_t
        lgfr    %r3,%r3                 # pid_t
        lgfr    %r4,%r4                 # int
        jg      sys_tgkill              # branch to system call
 
-       .globl  compat_sys_keyctl_wrapper
-compat_sys_keyctl_wrapper:
+ENTRY(compat_sys_keyctl_wrapper)
        llgfr   %r2,%r2                 # u32
        llgfr   %r3,%r3                 # u32
        llgfr   %r4,%r4                 # u32
@@ -1804,8 +1541,7 @@ compat_sys_keyctl_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      compat_sys_keyctl       # branch to system call
 
-       .globl  compat_sys_preadv_wrapper
-compat_sys_preadv_wrapper:
+ENTRY(compat_sys_preadv_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgtr   %r3,%r3                 # compat_iovec *
        llgfr   %r4,%r4                 # unsigned long
@@ -1813,8 +1549,7 @@ compat_sys_preadv_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      compat_sys_preadv       # branch to system call
 
-       .globl  compat_sys_pwritev_wrapper
-compat_sys_pwritev_wrapper:
+ENTRY(compat_sys_pwritev_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgtr   %r3,%r3                 # compat_iovec *
        llgfr   %r4,%r4                 # unsigned long
@@ -1822,16 +1557,14 @@ compat_sys_pwritev_wrapper:
        llgfr   %r6,%r6                 # u32
        jg      compat_sys_pwritev      # branch to system call
 
-       .globl  compat_sys_rt_tgsigqueueinfo_wrapper
-compat_sys_rt_tgsigqueueinfo_wrapper:
+ENTRY(compat_sys_rt_tgsigqueueinfo_wrapper)
        lgfr    %r2,%r2                 # compat_pid_t
        lgfr    %r3,%r3                 # compat_pid_t
        lgfr    %r4,%r4                 # int
        llgtr   %r5,%r5                 # struct compat_siginfo *
        jg      compat_sys_rt_tgsigqueueinfo_wrapper # branch to system call
 
-       .globl  sys_perf_event_open_wrapper
-sys_perf_event_open_wrapper:
+ENTRY(sys_perf_event_open_wrapper)
        llgtr   %r2,%r2                 # const struct perf_event_attr *
        lgfr    %r3,%r3                 # pid_t
        lgfr    %r4,%r4                 # int
@@ -1839,29 +1572,25 @@ sys_perf_event_open_wrapper:
        llgfr   %r6,%r6                 # unsigned long
        jg      sys_perf_event_open     # branch to system call
 
-       .globl  sys_clone_wrapper
-sys_clone_wrapper:
+ENTRY(sys_clone_wrapper)
        llgfr   %r2,%r2                 # unsigned long
        llgfr   %r3,%r3                 # unsigned long
        llgtr   %r4,%r4                 # int *
        llgtr   %r5,%r5                 # int *
        jg      sys_clone               # branch to system call
 
-       .globl  sys32_execve_wrapper
-sys32_execve_wrapper:
+ENTRY(sys32_execve_wrapper)
        llgtr   %r2,%r2                 # char *
        llgtr   %r3,%r3                 # compat_uptr_t *
        llgtr   %r4,%r4                 # compat_uptr_t *
        jg      sys32_execve            # branch to system call
 
-       .globl  sys_fanotify_init_wrapper
-sys_fanotify_init_wrapper:
+ENTRY(sys_fanotify_init_wrapper)
        llgfr   %r2,%r2                 # unsigned int
        llgfr   %r3,%r3                 # unsigned int
        jg      sys_fanotify_init       # branch to system call
 
-       .globl  sys_fanotify_mark_wrapper
-sys_fanotify_mark_wrapper:
+ENTRY(sys_fanotify_mark_wrapper)
        lgfr    %r2,%r2                 # int
        llgfr   %r3,%r3                 # unsigned int
        sllg    %r4,%r4,32              # get high word of 64bit mask
@@ -1870,16 +1599,14 @@ sys_fanotify_mark_wrapper:
        llgt    %r6,164(%r15)           # char *
        jg      sys_fanotify_mark       # branch to system call
 
-       .globl  sys_prlimit64_wrapper
-sys_prlimit64_wrapper:
+ENTRY(sys_prlimit64_wrapper)
        lgfr    %r2,%r2                 # pid_t
        llgfr   %r3,%r3                 # unsigned int
        llgtr   %r4,%r4                 # const struct rlimit64 __user *
        llgtr   %r5,%r5                 # struct rlimit64 __user *
        jg      sys_prlimit64           # branch to system call
 
-       .globl  sys_name_to_handle_at_wrapper
-sys_name_to_handle_at_wrapper:
+ENTRY(sys_name_to_handle_at_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # const char __user *
        llgtr   %r4,%r4                 # struct file_handle __user *
@@ -1887,21 +1614,18 @@ sys_name_to_handle_at_wrapper:
        lgfr    %r6,%r6                 # int
        jg      sys_name_to_handle_at
 
-       .globl  compat_sys_open_by_handle_at_wrapper
-compat_sys_open_by_handle_at_wrapper:
+ENTRY(compat_sys_open_by_handle_at_wrapper)
        lgfr    %r2,%r2                 # int
        llgtr   %r3,%r3                 # struct file_handle __user *
        lgfr    %r4,%r4                 # int
        jg      compat_sys_open_by_handle_at
 
-       .globl  compat_sys_clock_adjtime_wrapper
-compat_sys_clock_adjtime_wrapper:
+ENTRY(compat_sys_clock_adjtime_wrapper)
        lgfr    %r2,%r2                 # clockid_t (int)
        llgtr   %r3,%r3                 # struct compat_timex __user *
        jg      compat_sys_clock_adjtime
 
-       .globl  sys_syncfs_wrapper
-sys_syncfs_wrapper:
+ENTRY(sys_syncfs_wrapper)
        lgfr    %r2,%r2                 # int
        jg      sys_syncfs
 
index 0476174..3eab7cf 100644 (file)
@@ -9,8 +9,8 @@
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
-#include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/ptrace.h>
@@ -197,8 +197,7 @@ STACK_SIZE  = 1 << STACK_SHIFT
  * Returns:
  *  gpr2 = prev
  */
-       .globl  __switch_to
-__switch_to:
+ENTRY(__switch_to)
        basr    %r1,0
 0:     l       %r4,__THREAD_info(%r2)          # get thread_info of prev
        l       %r5,__THREAD_info(%r3)          # get thread_info of next
@@ -224,8 +223,7 @@ __critical_start:
  * are executed with interrupts enabled.
  */
 
-       .globl  system_call
-system_call:
+ENTRY(system_call)
        stpt    __LC_SYNC_ENTER_TIMER
 sysc_saveall:
        SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
@@ -388,8 +386,7 @@ sysc_tracenogo:
 #
 # a new process exits the kernel with ret_from_fork
 #
-       .globl  ret_from_fork
-ret_from_fork:
+ENTRY(ret_from_fork)
        l       %r13,__LC_SVC_NEW_PSW+4
        l       %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # forking a kernel thread ?
@@ -405,8 +402,7 @@ ret_from_fork:
 # kernel_execve function needs to deal with pt_regs that is not
 # at the usual place
 #
-       .globl  kernel_execve
-kernel_execve:
+ENTRY(kernel_execve)
        stm     %r12,%r15,48(%r15)
        lr      %r14,%r15
        l       %r13,__LC_SVC_NEW_PSW+4
@@ -438,8 +434,7 @@ kernel_execve:
  * Program check handler routine
  */
 
-       .globl  pgm_check_handler
-pgm_check_handler:
+ENTRY(pgm_check_handler)
 /*
  * First we need to check for a special case:
  * Single stepping an instruction that disables the PER event mask will
@@ -565,8 +560,7 @@ kernel_per:
  * IO interrupt handler routine
  */
 
-       .globl io_int_handler
-io_int_handler:
+ENTRY(io_int_handler)
        stck    __LC_INT_CLOCK
        stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
@@ -703,8 +697,7 @@ io_notify_resume:
  * External interrupt handler routine
  */
 
-       .globl  ext_int_handler
-ext_int_handler:
+ENTRY(ext_int_handler)
        stck    __LC_INT_CLOCK
        stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
@@ -731,8 +724,7 @@ __critical_end:
  * Machine check handler routines
  */
 
-       .globl mcck_int_handler
-mcck_int_handler:
+ENTRY(mcck_int_handler)
        stck    __LC_MCCK_CLOCK
        spt     __LC_CPU_TIMER_SAVE_AREA        # revalidate cpu timer
        lm      %r0,%r15,__LC_GPREGS_SAVE_AREA  # revalidate gprs
@@ -818,8 +810,7 @@ mcck_return:
  */
 #ifdef CONFIG_SMP
        __CPUINIT
-       .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
        basr    %r1,0
 restart_base:
        spt     restart_vtime-restart_base(%r1)
@@ -848,8 +839,7 @@ restart_vtime:
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-       .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
        basr    %r1,0
 restart_base:
        lpsw    restart_crash-restart_base(%r1)
index 17a6f83..66729eb 100644 (file)
@@ -5,10 +5,9 @@
 #include <linux/signal.h>
 #include <asm/ptrace.h>
 
-typedef void pgm_check_handler_t(struct pt_regs *, long, unsigned long);
-extern pgm_check_handler_t *pgm_check_table[128];
-pgm_check_handler_t do_protection_exception;
-pgm_check_handler_t do_dat_exception;
+void do_protection_exception(struct pt_regs *, long, unsigned long);
+void do_dat_exception(struct pt_regs *, long, unsigned long);
+void do_asce_exception(struct pt_regs *, long, unsigned long);
 
 extern int sysctl_userprocess_debug;
 
index d61967e..7a0fd42 100644 (file)
@@ -9,8 +9,8 @@
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
-#include <linux/linkage.h>
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/ptrace.h>
@@ -56,15 +56,28 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
 _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
                _TIF_SECCOMP>>8 | _TIF_SYSCALL_TRACEPOINT>>8)
+_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
 
+       .macro SPP newpp
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_SPP
+       jz      .+8
+       .insn   s,0xb2800000,\newpp
+#endif
+       .endm
+
        .macro  HANDLE_SIE_INTERCEPT
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
-       lg      %r3,__LC_SIE_HOOK
-       ltgr    %r3,%r3
+       tm      __TI_flags+6(%r12),_TIF_SIE>>8
        jz      0f
-       basr    %r14,%r3
+       SPP     __LC_CMF_HPP                    # set host id
+       clc     SP_PSW+8(8,%r15),BASED(.Lsie_loop)
+       jl      0f
+       clc     SP_PSW+8(8,%r15),BASED(.Lsie_done)
+       jhe     0f
+       mvc     SP_PSW+8(8,%r15),BASED(.Lsie_loop)
 0:
 #endif
        .endm
@@ -206,8 +219,7 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
  * Returns:
  *  gpr2 = prev
  */
-       .globl  __switch_to
-__switch_to:
+ENTRY(__switch_to)
        lg      %r4,__THREAD_info(%r2)          # get thread_info of prev
        lg      %r5,__THREAD_info(%r3)          # get thread_info of next
        tm      __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
@@ -232,8 +244,7 @@ __critical_start:
  * are executed with interrupts enabled.
  */
 
-       .globl  system_call
-system_call:
+ENTRY(system_call)
        stpt    __LC_SYNC_ENTER_TIMER
 sysc_saveall:
        SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
@@ -395,8 +406,7 @@ sysc_tracenogo:
 #
 # a new process exits the kernel with ret_from_fork
 #
-       .globl  ret_from_fork
-ret_from_fork:
+ENTRY(ret_from_fork)
        lg      %r13,__LC_SVC_NEW_PSW+8
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      SP_PSW+1(%r15),0x01     # forking a kernel thread ?
@@ -411,8 +421,7 @@ ret_from_fork:
 # kernel_execve function needs to deal with pt_regs that is not
 # at the usual place
 #
-       .globl  kernel_execve
-kernel_execve:
+ENTRY(kernel_execve)
        stmg    %r12,%r15,96(%r15)
        lgr     %r14,%r15
        aghi    %r15,-SP_SIZE
@@ -442,8 +451,7 @@ kernel_execve:
  * Program check handler routine
  */
 
-       .globl  pgm_check_handler
-pgm_check_handler:
+ENTRY(pgm_check_handler)
 /*
  * First we need to check for a special case:
  * Single stepping an instruction that disables the PER event mask will
@@ -465,6 +473,7 @@ pgm_check_handler:
        xc      SP_ILC(4,%r15),SP_ILC(%r15)
        mvc     SP_PSW(16,%r15),__LC_PGM_OLD_PSW
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      pgm_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -472,7 +481,6 @@ pgm_check_handler:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
        LAST_BREAK
 pgm_no_vtime:
-       HANDLE_SIE_INTERCEPT
        stg     %r11,SP_ARGS(%r15)
        lgf     %r3,__LC_PGM_ILC        # load program interruption code
        lg      %r4,__LC_TRANS_EXC_CODE
@@ -507,6 +515,7 @@ pgm_per_std:
        CREATE_STACK_FRAME __LC_SAVE_AREA
        mvc     SP_PSW(16,%r15),__LC_PGM_OLD_PSW
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      pgm_no_vtime2
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -514,7 +523,6 @@ pgm_per_std:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
        LAST_BREAK
 pgm_no_vtime2:
-       HANDLE_SIE_INTERCEPT
        lg      %r1,__TI_task(%r12)
        tm      SP_PSW+1(%r15),0x01     # kernel per event ?
        jz      kernel_per
@@ -571,14 +579,14 @@ kernel_per:
 /*
  * IO interrupt handler routine
  */
-       .globl io_int_handler
-io_int_handler:
+ENTRY(io_int_handler)
        stck    __LC_INT_CLOCK
        stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40
        CREATE_STACK_FRAME __LC_SAVE_AREA+40
        mvc     SP_PSW(16,%r15),0(%r12) # move user PSW to stack
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      io_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -586,7 +594,6 @@ io_int_handler:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
        LAST_BREAK
 io_no_vtime:
-       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
        brasl   %r14,do_IRQ             # call standard irq handler
@@ -706,14 +713,14 @@ io_notify_resume:
 /*
  * External interrupt handler routine
  */
-       .globl  ext_int_handler
-ext_int_handler:
+ENTRY(ext_int_handler)
        stck    __LC_INT_CLOCK
        stpt    __LC_ASYNC_ENTER_TIMER
        SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40
        CREATE_STACK_FRAME __LC_SAVE_AREA+40
        mvc     SP_PSW(16,%r15),0(%r12) # move user PSW to stack
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      ext_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
@@ -721,7 +728,6 @@ ext_int_handler:
        mvc     __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
        LAST_BREAK
 ext_no_vtime:
-       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        lghi    %r1,4096
        la      %r2,SP_PTREGS(%r15)     # address of register-save area
@@ -736,8 +742,7 @@ __critical_end:
 /*
  * Machine check handler routines
  */
-       .globl mcck_int_handler
-mcck_int_handler:
+ENTRY(mcck_int_handler)
        stck    __LC_MCCK_CLOCK
        la      %r1,4095                # revalidate r1
        spt     __LC_CPU_TIMER_SAVE_AREA-4095(%r1)      # revalidate cpu timer
@@ -785,6 +790,7 @@ mcck_int_main:
        lg      %r12,__LC_THREAD_INFO   # load pointer to thread_info struct
        tm      __LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
        jno     mcck_no_vtime           # no -> no timer update
+       HANDLE_SIE_INTERCEPT
        tm      SP_PSW+1(%r15),0x01     # interrupting from user ?
        jz      mcck_no_vtime
        UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER
@@ -804,7 +810,6 @@ mcck_no_vtime:
        stosm   __SF_EMPTY(%r15),0x04   # turn dat on
        tm      __TI_flags+7(%r12),_TIF_MCCK_PENDING
        jno     mcck_return
-       HANDLE_SIE_INTERCEPT
        TRACE_IRQS_OFF
        brasl   %r14,s390_handle_mcck
        TRACE_IRQS_ON
@@ -823,8 +828,7 @@ mcck_done:
  */
 #ifdef CONFIG_SMP
        __CPUINIT
-       .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
        basr    %r1,0
 restart_base:
        spt     restart_vtime-restart_base(%r1)
@@ -851,8 +855,7 @@ restart_vtime:
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
  */
-       .globl restart_int_handler
-restart_int_handler:
+ENTRY(restart_int_handler)
        basr    %r1,0
 restart_base:
        lpswe   restart_crash-restart_base(%r1)
@@ -1036,6 +1039,56 @@ cleanup_io_restore_insn:
 .Lcritical_end:
                .quad   __critical_end
 
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+/*
+ * sie64a calling convention:
+ * %r2 pointer to sie control block
+ * %r3 guest register save area
+ */
+ENTRY(sie64a)
+       stmg    %r6,%r14,__SF_GPRS(%r15)        # save kernel registers
+       stg     %r2,__SF_EMPTY(%r15)            # save control block pointer
+       stg     %r3,__SF_EMPTY+8(%r15)          # save guest register save area
+       lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+       oi      __TI_flags+6(%r14),_TIF_SIE>>8
+sie_loop:
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+       tm      __TI_flags+7(%r14),_TIF_EXIT_SIE
+       jnz     sie_exit
+       lg      %r14,__SF_EMPTY(%r15)           # get control block pointer
+       SPP     __SF_EMPTY(%r15)                # set guest id
+       sie     0(%r14)
+sie_done:
+       SPP     __LC_CMF_HPP                    # set host id
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+sie_exit:
+       ni      __TI_flags+6(%r14),255-(_TIF_SIE>>8)
+       lg      %r14,__SF_EMPTY+8(%r15)         # load guest register save area
+       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
+       lmg     %r6,%r14,__SF_GPRS(%r15)        # restore kernel registers
+       lghi    %r2,0
+       br      %r14
+sie_fault:
+       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
+       ni      __TI_flags+6(%r14),255-(_TIF_SIE>>8)
+       lg      %r14,__SF_EMPTY+8(%r15)         # load guest register save area
+       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
+       lmg     %r6,%r14,__SF_GPRS(%r15)        # restore kernel registers
+       lghi    %r2,-EFAULT
+       br      %r14
+
+       .align  8
+.Lsie_loop:
+       .quad   sie_loop
+.Lsie_done:
+       .quad   sie_done
+
+       .section __ex_table,"a"
+       .quad   sie_loop,sie_fault
+       .previous
+#endif
+
                .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esame
        .globl  sys_call_table
index fb317bf..2d781ba 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
@@ -383,8 +384,7 @@ iplstart:
 # doesn't need a builtin ipl record.
 #
        .org    0x800
-       .globl  start
-start:
+ENTRY(start)
        stm     %r0,%r15,0x07b0         # store registers
        basr    %r12,%r0
 .base:
@@ -448,8 +448,7 @@ start:
 # or linload or SALIPL
 #
        .org    0x10000
-       .globl  startup
-startup:
+ENTRY(startup)
        basr    %r13,0                  # get base
 .LPG0:
        xc      0x200(256),0x200        # partially clear lowcore
index b8f8dc1..f21954b 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
 __HEAD
-       .globl  startup_continue
-startup_continue:
+ENTRY(startup_continue)
        basr    %r13,0                  # get base
 .LPG1:
 
@@ -45,7 +45,7 @@ startup_continue:
                                        # virtual and never return ...
        .align  8
 .Lentry:.long  0x00080000,0x80000000 + _stext
-.Lctl: .long   0x04b50002              # cr0: various things
+.Lctl: .long   0x04b50000              # cr0: various things
        .long   0                       # cr1: primary space segment table
        .long   .Lduct                  # cr2: dispatchable unit control table
        .long   0                       # cr3: instruction authorization
@@ -78,8 +78,7 @@ startup_continue:
 .Lbase_cc:
        .long   sched_clock_base_cc
 
-       .globl  _ehead
-_ehead:
+ENTRY(_ehead)
 
 #ifdef CONFIG_SHARED_KERNEL
        .org    0x100000 - 0x11000      # head.o ends at 0x11000
@@ -88,8 +87,8 @@ _ehead:
 #
 # startup-code, running in absolute addressing mode
 #
-       .globl  _stext
-_stext:        basr    %r13,0                  # get base
+ENTRY(_stext)
+       basr    %r13,0                  # get base
 .LPG3:
 # check control registers
        stctl   %c0,%c15,0(%r15)
index cdef687..ae5d492 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
 __HEAD
-       .globl  startup_continue
-startup_continue:
+ENTRY(startup_continue)
        larl    %r1,sched_clock_base_cc
        mvc     0(8,%r1),__LC_LAST_UPDATE_CLOCK
        larl    %r13,.LPG1              # get base
@@ -46,7 +46,7 @@ startup_continue:
        .align  16
 .LPG1:
 .Lentry:.quad  0x0000000180000000,_stext
-.Lctl: .quad   0x04350002              # cr0: various things
+.Lctl: .quad   0x04040000              # cr0: AFP registers & secondary space
        .quad   0                       # cr1: primary space segment table
        .quad   .Lduct                  # cr2: dispatchable unit control table
        .quad   0                       # cr3: instruction authorization
@@ -76,8 +76,7 @@ startup_continue:
        .long   0x80000000,0,0,0        # invalid access-list entries
        .endr
 
-       .globl  _ehead
-_ehead:
+ENTRY(_ehead)
 
 #ifdef CONFIG_SHARED_KERNEL
        .org    0x100000 - 0x11000      # head.o ends at 0x11000
@@ -86,8 +85,8 @@ _ehead:
 #
 # startup-code, running in absolute addressing mode
 #
-       .globl  _stext
-_stext:        basr    %r13,0                  # get base
+ENTRY(_stext)
+       basr    %r13,0                  # get base
 .LPG3:
 # check control registers
        stctg   %c0,%c15,0(%r15)
index e3264f6..1f4050d 100644 (file)
@@ -87,15 +87,6 @@ int show_interrupts(struct seq_file *p, void *v)
         return 0;
 }
 
-/*
- * For compatibilty only. S/390 specific setup of interrupts et al. is done
- * much later in init_channel_subsystem().
- */
-void __init init_IRQ(void)
-{
-       /* nothing... */
-}
-
 /*
  * Switch to the asynchronous interrupt stack for softirq execution.
  */
@@ -144,28 +135,45 @@ void init_irq_proc(void)
 #endif
 
 /*
- * ext_int_hash[index] is the start of the list for all external interrupts
- * that hash to this index. With the current set of external interrupts
- * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000
- * iucv and 0x2603 pfault) this is always the first element.
+ * ext_int_hash[index] is the list head for all external interrupts that hash
+ * to this index.
  */
+static struct list_head ext_int_hash[256];
 
 struct ext_int_info {
-       struct ext_int_info *next;
        ext_int_handler_t handler;
        u16 code;
+       struct list_head entry;
+       struct rcu_head rcu;
 };
 
-static struct ext_int_info *ext_int_hash[256];
+/* ext_int_hash_lock protects the handler lists for external interrupts */
+DEFINE_SPINLOCK(ext_int_hash_lock);
+
+static void __init init_external_interrupts(void)
+{
+       int idx;
+
+       for (idx = 0; idx < ARRAY_SIZE(ext_int_hash); idx++)
+               INIT_LIST_HEAD(&ext_int_hash[idx]);
+}
 
 static inline int ext_hash(u16 code)
 {
        return (code + (code >> 9)) & 0xff;
 }
 
+static void ext_int_hash_update(struct rcu_head *head)
+{
+       struct ext_int_info *p = container_of(head, struct ext_int_info, rcu);
+
+       kfree(p);
+}
+
 int register_external_interrupt(u16 code, ext_int_handler_t handler)
 {
        struct ext_int_info *p;
+       unsigned long flags;
        int index;
 
        p = kmalloc(sizeof(*p), GFP_ATOMIC);
@@ -174,33 +182,27 @@ int register_external_interrupt(u16 code, ext_int_handler_t handler)
        p->code = code;
        p->handler = handler;
        index = ext_hash(code);
-       p->next = ext_int_hash[index];
-       ext_int_hash[index] = p;
+
+       spin_lock_irqsave(&ext_int_hash_lock, flags);
+       list_add_rcu(&p->entry, &ext_int_hash[index]);
+       spin_unlock_irqrestore(&ext_int_hash_lock, flags);
        return 0;
 }
 EXPORT_SYMBOL(register_external_interrupt);
 
 int unregister_external_interrupt(u16 code, ext_int_handler_t handler)
 {
-       struct ext_int_info *p, *q;
-       int index;
+       struct ext_int_info *p;
+       unsigned long flags;
+       int index = ext_hash(code);
 
-       index = ext_hash(code);
-       q = NULL;
-       p = ext_int_hash[index];
-       while (p) {
-               if (p->code == code && p->handler == handler)
-                       break;
-               q = p;
-               p = p->next;
-       }
-       if (!p)
-               return -ENOENT;
-       if (q)
-               q->next = p->next;
-       else
-               ext_int_hash[index] = p->next;
-       kfree(p);
+       spin_lock_irqsave(&ext_int_hash_lock, flags);
+       list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
+               if (p->code == code && p->handler == handler) {
+                       list_del_rcu(&p->entry);
+                       call_rcu(&p->rcu, ext_int_hash_update);
+               }
+       spin_unlock_irqrestore(&ext_int_hash_lock, flags);
        return 0;
 }
 EXPORT_SYMBOL(unregister_external_interrupt);
@@ -224,15 +226,22 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code,
        kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
        if (code != 0x1004)
                __get_cpu_var(s390_idle).nohz_delay = 1;
+
        index = ext_hash(code);
-       for (p = ext_int_hash[index]; p; p = p->next) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
                if (likely(p->code == code))
                        p->handler(ext_int_code, param32, param64);
-       }
+       rcu_read_unlock();
        irq_exit();
        set_irq_regs(old_regs);
 }
 
+void __init init_IRQ(void)
+{
+       init_external_interrupts();
+}
+
 static DEFINE_SPINLOCK(sc_irq_lock);
 static int sc_irq_refcount;
 
index 1e6a557..7e2c38b 100644 (file)
@@ -5,21 +5,19 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
        .section .kprobes.text, "ax"
 
-       .globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
        br      %r14
 
-       .globl _mcount
-_mcount:
+ENTRY(_mcount)
 #ifdef CONFIG_DYNAMIC_FTRACE
        br      %r14
 
-       .globl ftrace_caller
-ftrace_caller:
+ENTRY(ftrace_caller)
 #endif
        stm     %r2,%r5,16(%r15)
        bras    %r1,2f
@@ -41,8 +39,7 @@ ftrace_caller:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        l       %r2,100(%r15)
        l       %r3,152(%r15)
-       .globl  ftrace_graph_caller
-ftrace_graph_caller:
+ENTRY(ftrace_graph_caller)
 # The bras instruction gets runtime patched to call prepare_ftrace_return.
 # See ftrace_enable_ftrace_graph_caller. The patched instruction is:
 #      bras    %r14,prepare_ftrace_return
@@ -56,8 +53,7 @@ ftrace_graph_caller:
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
-       .globl  return_to_handler
-return_to_handler:
+ENTRY(return_to_handler)
        stm     %r2,%r5,16(%r15)
        st      %r14,56(%r15)
        lr      %r0,%r15
index e736672..f70cade 100644 (file)
@@ -5,21 +5,19 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
        .section .kprobes.text, "ax"
 
-       .globl ftrace_stub
-ftrace_stub:
+ENTRY(ftrace_stub)
        br      %r14
 
-       .globl _mcount
-_mcount:
+ENTRY(_mcount)
 #ifdef CONFIG_DYNAMIC_FTRACE
        br      %r14
 
-       .globl ftrace_caller
-ftrace_caller:
+ENTRY(ftrace_caller)
 #endif
        larl    %r1,function_trace_stop
        icm     %r1,0xf,0(%r1)
@@ -37,8 +35,7 @@ ftrace_caller:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        lg      %r2,168(%r15)
        lg      %r3,272(%r15)
-       .globl  ftrace_graph_caller
-ftrace_graph_caller:
+ENTRY(ftrace_graph_caller)
 # The bras instruction gets runtime patched to call prepare_ftrace_return.
 # See ftrace_enable_ftrace_graph_caller. The patched instruction is:
 #      bras    %r14,prepare_ftrace_return
@@ -52,8 +49,7 @@ ftrace_graph_caller:
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
-       .globl  return_to_handler
-return_to_handler:
+ENTRY(return_to_handler)
        stmg    %r2,%r5,32(%r15)
        lgr     %r1,%r15
        aghi    %r15,-160
index cb899d9..303d961 100644 (file)
@@ -6,14 +6,15 @@
  *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
 #
 # do_reipl_asm
 # Parameter: r2 = schid of reipl device
 #
-               .globl  do_reipl_asm
-do_reipl_asm:  basr    %r13,0
+ENTRY(do_reipl_asm)
+               basr    %r13,0
 .Lpg0:         lpsw    .Lnewpsw-.Lpg0(%r13)
 .Lpg1:         # do store status of all registers
 
index 9eabbc9..78eb7cf 100644 (file)
@@ -4,6 +4,7 @@
  *              Denis Joseph Barrow,
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 
 #
@@ -11,8 +12,8 @@
 # Parameter: r2 = schid of reipl device
 #
 
-               .globl  do_reipl_asm
-do_reipl_asm:  basr    %r13,0
+ENTRY(do_reipl_asm)
+               basr    %r13,0
 .Lpg0:         lpswe   .Lnewpsw-.Lpg0(%r13)
 .Lpg1:         # do store status of all registers
 
index 3b456b8..c91d70a 100644 (file)
@@ -8,6 +8,8 @@
  *
  */
 
+#include <linux/linkage.h>
+
 /*
  * moves the new kernel to its destination...
  * %r2 = pointer to first kimage_entry_t
@@ -22,8 +24,7 @@
  */
 
        .text
-       .globl          relocate_kernel
-       relocate_kernel:
+ENTRY(relocate_kernel)
                basr    %r13,0          # base address
        .base:
                stnsm   sys_msk-.base(%r13),0xfb        # disable DAT
                .byte   0
                .align  8
        relocate_kernel_end:
+       .align 8
        .globl  relocate_kernel_len
        relocate_kernel_len:
                .quad   relocate_kernel_end - relocate_kernel
index 1f9ea20..7c3ce58 100644 (file)
@@ -8,6 +8,8 @@
  *
  */
 
+#include <linux/linkage.h>
+
 /*
  * moves the new kernel to its destination...
  * %r2 = pointer to first kimage_entry_t
@@ -23,8 +25,7 @@
  */
 
        .text
-       .globl          relocate_kernel
-       relocate_kernel:
+ENTRY(relocate_kernel)
                basr    %r13,0          # base address
        .base:
                stnsm   sys_msk-.base(%r13),0xfb        # disable DAT
                .byte   0
                .align  8
        relocate_kernel_end:
+       .align 8
        .globl  relocate_kernel_len
        relocate_kernel_len:
                .quad   relocate_kernel_end - relocate_kernel
index 656fcbb..57b5366 100644 (file)
@@ -1,6 +1,10 @@
 #include <linux/module.h>
+#include <linux/kvm_host.h>
 #include <asm/ftrace.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
 EXPORT_SYMBOL(_mcount);
 #endif
+#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
+EXPORT_SYMBOL(sie64a);
+#endif
index 2e82fdd..95792d8 100644 (file)
@@ -8,6 +8,8 @@
  *
  */
 
+#include <linux/linkage.h>
+
 LC_EXT_NEW_PSW         = 0x58                  # addr of ext int handler
 LC_EXT_NEW_PSW_64      = 0x1b0                 # addr of ext int handler 64 bit
 LC_EXT_INT_PARAM       = 0x80                  # addr of ext int parameter
@@ -260,8 +262,7 @@ _sclp_print:
 #   R2 = 0 on success, 1 on failure
 #
 
-       .globl _sclp_print_early
-_sclp_print_early:
+ENTRY(_sclp_print_early)
        stm     %r6,%r15,24(%r15)               # save registers
        ahi     %r15,-96                        # create stack frame
 #ifdef CONFIG_64BIT
index 1d55c95..a6d85c0 100644 (file)
@@ -654,7 +654,8 @@ int __cpu_disable(void)
        /* disable all external interrupts */
        cr_parms.orvals[0] = 0;
        cr_parms.andvals[0] = ~(1 << 15 | 1 << 14 | 1 << 13 | 1 << 11 |
-                               1 << 10 | 1 <<  9 | 1 <<  6 | 1 <<  4);
+                               1 << 10 | 1 <<  9 | 1 <<  6 | 1 <<  5 |
+                               1 <<  4);
        /* disable all I/O interrupts */
        cr_parms.orvals[6] = 0;
        cr_parms.andvals[6] = ~(1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 |
index 20530dd..bfe070b 100644 (file)
@@ -5,6 +5,7 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
 
@@ -16,9 +17,7 @@
 #           %r6 - destination cpu
 
        .section .text
-       .align 4
-       .globl smp_switch_to_cpu
-smp_switch_to_cpu:
+ENTRY(smp_switch_to_cpu)
        stm     %r6,%r15,__SF_GPRS(%r15)
        lr      %r1,%r15
        ahi     %r15,-STACK_FRAME_OVERHEAD
@@ -33,8 +32,7 @@ smp_switch_to_cpu:
        brc     2,2b                    /* busy, try again */
 3:     j       3b
 
-       .globl  smp_restart_cpu
-smp_restart_cpu:
+ENTRY(smp_restart_cpu)
        basr    %r13,0
 0:     la      %r1,.gprregs_addr-0b(%r13)
        l       %r1,0(%r1)
index 5be3f43..fcc42d7 100644 (file)
@@ -5,6 +5,7 @@
  *
  */
 
+#include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
 
@@ -16,9 +17,7 @@
 #           %r6 - destination cpu
 
        .section .text
-       .align 4
-       .globl smp_switch_to_cpu
-smp_switch_to_cpu:
+ENTRY(smp_switch_to_cpu)
        stmg    %r6,%r15,__SF_GPRS(%r15)
        lgr     %r1,%r15
        aghi    %r15,-STACK_FRAME_OVERHEAD
@@ -31,8 +30,7 @@ smp_switch_to_cpu:
        brc     2,2b                    /* busy, try again */
 3:     j       3b
 
-       .globl  smp_restart_cpu
-smp_restart_cpu:
+ENTRY(smp_restart_cpu)
        larl    %r1,.gprregs
        lmg     %r0,%r15,0(%r1)
 1:     sigp    %r0,%r5,__SIGP_SENSE    /* Wait for calling CPU */
index 1f066e4..51bcdb5 100644 (file)
@@ -7,6 +7,7 @@
  *           Michael Holzheu <holzheu@linux.vnet.ibm.com>
  */
 
+#include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
@@ -22,9 +23,7 @@
  * This function runs with disabled interrupts.
  */
        .section .text
-       .align  4
-       .globl swsusp_arch_suspend
-swsusp_arch_suspend:
+ENTRY(swsusp_arch_suspend)
        stmg    %r6,%r15,__SF_GPRS(%r15)
        lgr     %r1,%r15
        aghi    %r15,-STACK_FRAME_OVERHEAD
@@ -112,8 +111,7 @@ swsusp_arch_suspend:
  * Then we return to the function that called swsusp_arch_suspend().
  * swsusp_arch_resume() runs with disabled interrupts.
  */
-       .globl swsusp_arch_resume
-swsusp_arch_resume:
+ENTRY(swsusp_arch_resume)
        stmg    %r6,%r15,__SF_GPRS(%r15)
        lgr     %r1,%r15
        aghi    %r15,-STACK_FRAME_OVERHEAD
index a63d34c..e9372c7 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/tracehook.h>
+#include <linux/ptrace.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <asm/debug.h>
 #include "entry.h"
 
-pgm_check_handler_t *pgm_check_table[128];
+void (*pgm_check_table[128])(struct pt_regs *, long, unsigned long);
 
 int show_unhandled_signals;
 
-extern pgm_check_handler_t do_protection_exception;
-extern pgm_check_handler_t do_dat_exception;
-extern pgm_check_handler_t do_asce_exception;
-
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
 
 #ifndef CONFIG_64BIT
@@ -329,10 +325,17 @@ static inline void __user *get_psw_address(struct pt_regs *regs,
 
 void __kprobes do_per_trap(struct pt_regs *regs)
 {
+       siginfo_t info;
+
        if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
                return;
-       if (current->ptrace)
-               force_sig(SIGTRAP, current);
+       if (!current->ptrace)
+               return;
+       info.si_signo = SIGTRAP;
+       info.si_errno = 0;
+       info.si_code = TRAP_HWBKPT;
+       info.si_addr = (void *) current->thread.per_event.address;
+       force_sig_info(SIGTRAP, &info, current);
 }
 
 static void default_trap_handler(struct pt_regs *regs, long pgm_int_code,
@@ -425,9 +428,13 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
                if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
                        return;
                if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
-                       if (current->ptrace)
-                               force_sig(SIGTRAP, current);
-                       else
+                       if (current->ptrace) {
+                               info.si_signo = SIGTRAP;
+                               info.si_errno = 0;
+                               info.si_code = TRAP_BRKPT;
+                               info.si_addr = location;
+                               force_sig_info(SIGTRAP, &info, current);
+                       } else
                                signal = SIGILL;
 #ifdef CONFIG_MATHEMU
                } else if (opcode[0] == 0xb3) {
@@ -489,9 +496,8 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
 
 
 #ifdef CONFIG_MATHEMU
-asmlinkage void specification_exception(struct pt_regs *regs,
-                                       long pgm_int_code,
-                                       unsigned long trans_exc_code)
+void specification_exception(struct pt_regs *regs, long pgm_int_code,
+                            unsigned long trans_exc_code)
 {
         __u8 opcode[6];
        __u16 __user *location = NULL;
@@ -648,7 +654,7 @@ static void space_switch_exception(struct pt_regs *regs, long pgm_int_code,
        do_trap(pgm_int_code, SIGILL, "space switch event", regs, &info);
 }
 
-asmlinkage void __kprobes kernel_stack_overflow(struct pt_regs * regs)
+void __kprobes kernel_stack_overflow(struct pt_regs * regs)
 {
        bust_spinlocks(1);
        printk("Kernel stack overflow.\n");
index 860d265..3975722 100644 (file)
@@ -10,5 +10,5 @@ common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
 
 ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
-kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
+kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o diag.o
 obj-$(CONFIG_KVM) += kvm.o
index 03c716a..c86f6ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * gaccess.h -  access guest memory
+ * access.h -  access guest memory
  *
  * Copyright IBM Corp. 2008,2009
  *
@@ -22,20 +22,13 @@ static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
                                               unsigned long guestaddr)
 {
        unsigned long prefix  = vcpu->arch.sie_block->prefix;
-       unsigned long origin  = vcpu->arch.sie_block->gmsor;
-       unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
        if (guestaddr < 2 * PAGE_SIZE)
                guestaddr += prefix;
        else if ((guestaddr >= prefix) && (guestaddr < prefix + 2 * PAGE_SIZE))
                guestaddr -= prefix;
 
-       if (guestaddr > memsize)
-               return (void __user __force *) ERR_PTR(-EFAULT);
-
-       guestaddr += origin;
-
-       return (void __user *) guestaddr;
+       return (void __user *) gmap_fault(guestaddr, vcpu->arch.gmap);
 }
 
 static inline int get_guest_u64(struct kvm_vcpu *vcpu, unsigned long guestaddr,
@@ -141,11 +134,11 @@ static inline int put_guest_u8(struct kvm_vcpu *vcpu, unsigned long guestaddr,
 
 static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
                                       unsigned long guestdest,
-                                      const void *from, unsigned long n)
+                                      void *from, unsigned long n)
 {
        int rc;
        unsigned long i;
-       const u8 *data = from;
+       u8 *data = from;
 
        for (i = 0; i < n; i++) {
                rc = put_guest_u8(vcpu, guestdest++, *(data++));
@@ -155,12 +148,95 @@ static inline int __copy_to_guest_slow(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+static inline int __copy_to_guest_fast(struct kvm_vcpu *vcpu,
+                                      unsigned long guestdest,
+                                      void *from, unsigned long n)
+{
+       int r;
+       void __user *uptr;
+       unsigned long size;
+
+       if (guestdest + n < guestdest)
+               return -EFAULT;
+
+       /* simple case: all within one segment table entry? */
+       if ((guestdest & PMD_MASK) == ((guestdest+n) & PMD_MASK)) {
+               uptr = (void __user *) gmap_fault(guestdest, vcpu->arch.gmap);
+
+               if (IS_ERR((void __force *) uptr))
+                       return PTR_ERR((void __force *) uptr);
+
+               r = copy_to_user(uptr, from, n);
+
+               if (r)
+                       r = -EFAULT;
+
+               goto out;
+       }
+
+       /* copy first segment */
+       uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
+
+       size = PMD_SIZE - (guestdest & ~PMD_MASK);
+
+       r = copy_to_user(uptr, from, size);
+
+       if (r) {
+               r = -EFAULT;
+               goto out;
+       }
+       from += size;
+       n -= size;
+       guestdest += size;
+
+       /* copy full segments */
+       while (n >= PMD_SIZE) {
+               uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+               if (IS_ERR((void __force *) uptr))
+                       return PTR_ERR((void __force *) uptr);
+
+               r = copy_to_user(uptr, from, PMD_SIZE);
+
+               if (r) {
+                       r = -EFAULT;
+                       goto out;
+               }
+               from += PMD_SIZE;
+               n -= PMD_SIZE;
+               guestdest += PMD_SIZE;
+       }
+
+       /* copy the tail segment */
+       if (n) {
+               uptr = (void __user *)gmap_fault(guestdest, vcpu->arch.gmap);
+
+               if (IS_ERR((void __force *) uptr))
+                       return PTR_ERR((void __force *) uptr);
+
+               r = copy_to_user(uptr, from, n);
+
+               if (r)
+                       r = -EFAULT;
+       }
+out:
+       return r;
+}
+
+static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
+                                        unsigned long guestdest,
+                                        void *from, unsigned long n)
+{
+       return __copy_to_guest_fast(vcpu, guestdest, from, n);
+}
+
 static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
-                               const void *from, unsigned long n)
+                               void *from, unsigned long n)
 {
        unsigned long prefix  = vcpu->arch.sie_block->prefix;
-       unsigned long origin  = vcpu->arch.sie_block->gmsor;
-       unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
        if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
                goto slowpath;
@@ -177,15 +253,7 @@ static inline int copy_to_guest(struct kvm_vcpu *vcpu, unsigned long guestdest,
        else if ((guestdest >= prefix) && (guestdest < prefix + 2 * PAGE_SIZE))
                guestdest -= prefix;
 
-       if (guestdest + n > memsize)
-               return -EFAULT;
-
-       if (guestdest + n < guestdest)
-               return -EFAULT;
-
-       guestdest += origin;
-
-       return copy_to_user((void __user *) guestdest, from, n);
+       return __copy_to_guest_fast(vcpu, guestdest, from, n);
 slowpath:
        return __copy_to_guest_slow(vcpu, guestdest, from, n);
 }
@@ -206,74 +274,113 @@ static inline int __copy_from_guest_slow(struct kvm_vcpu *vcpu, void *to,
        return 0;
 }
 
-static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
-                                 unsigned long guestsrc, unsigned long n)
+static inline int __copy_from_guest_fast(struct kvm_vcpu *vcpu, void *to,
+                                        unsigned long guestsrc,
+                                        unsigned long n)
 {
-       unsigned long prefix  = vcpu->arch.sie_block->prefix;
-       unsigned long origin  = vcpu->arch.sie_block->gmsor;
-       unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+       int r;
+       void __user *uptr;
+       unsigned long size;
 
-       if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
-               goto slowpath;
+       if (guestsrc + n < guestsrc)
+               return -EFAULT;
 
-       if ((guestsrc < prefix) && (guestsrc + n > prefix))
-               goto slowpath;
+       /* simple case: all within one segment table entry? */
+       if ((guestsrc & PMD_MASK) == ((guestsrc+n) & PMD_MASK)) {
+               uptr = (void __user *) gmap_fault(guestsrc, vcpu->arch.gmap);
 
-       if ((guestsrc < prefix + 2 * PAGE_SIZE)
-           && (guestsrc + n > prefix + 2 * PAGE_SIZE))
-               goto slowpath;
+               if (IS_ERR((void __force *) uptr))
+                       return PTR_ERR((void __force *) uptr);
 
-       if (guestsrc < 2 * PAGE_SIZE)
-               guestsrc += prefix;
-       else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
-               guestsrc -= prefix;
+               r = copy_from_user(to, uptr, n);
 
-       if (guestsrc + n > memsize)
-               return -EFAULT;
+               if (r)
+                       r = -EFAULT;
 
-       if (guestsrc + n < guestsrc)
-               return -EFAULT;
+               goto out;
+       }
 
-       guestsrc += origin;
+       /* copy first segment */
+       uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
 
-       return copy_from_user(to, (void __user *) guestsrc, n);
-slowpath:
-       return __copy_from_guest_slow(vcpu, to, guestsrc, n);
-}
+       if (IS_ERR((void __force *) uptr))
+               return PTR_ERR((void __force *) uptr);
 
-static inline int copy_to_guest_absolute(struct kvm_vcpu *vcpu,
-                                        unsigned long guestdest,
-                                        const void *from, unsigned long n)
-{
-       unsigned long origin  = vcpu->arch.sie_block->gmsor;
-       unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+       size = PMD_SIZE - (guestsrc & ~PMD_MASK);
 
-       if (guestdest + n > memsize)
-               return -EFAULT;
+       r = copy_from_user(to, uptr, size);
 
-       if (guestdest + n < guestdest)
-               return -EFAULT;
+       if (r) {
+               r = -EFAULT;
+               goto out;
+       }
+       to += size;
+       n -= size;
+       guestsrc += size;
+
+       /* copy full segments */
+       while (n >= PMD_SIZE) {
+               uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
+
+               if (IS_ERR((void __force *) uptr))
+                       return PTR_ERR((void __force *) uptr);
+
+               r = copy_from_user(to, uptr, PMD_SIZE);
+
+               if (r) {
+                       r = -EFAULT;
+                       goto out;
+               }
+               to += PMD_SIZE;
+               n -= PMD_SIZE;
+               guestsrc += PMD_SIZE;
+       }
+
+       /* copy the tail segment */
+       if (n) {
+               uptr = (void __user *)gmap_fault(guestsrc, vcpu->arch.gmap);
 
-       guestdest += origin;
+               if (IS_ERR((void __force *) uptr))
+                       return PTR_ERR((void __force *) uptr);
 
-       return copy_to_user((void __user *) guestdest, from, n);
+               r = copy_from_user(to, uptr, n);
+
+               if (r)
+                       r = -EFAULT;
+       }
+out:
+       return r;
 }
 
 static inline int copy_from_guest_absolute(struct kvm_vcpu *vcpu, void *to,
                                           unsigned long guestsrc,
                                           unsigned long n)
 {
-       unsigned long origin  = vcpu->arch.sie_block->gmsor;
-       unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
+       return __copy_from_guest_fast(vcpu, to, guestsrc, n);
+}
 
-       if (guestsrc + n > memsize)
-               return -EFAULT;
+static inline int copy_from_guest(struct kvm_vcpu *vcpu, void *to,
+                                 unsigned long guestsrc, unsigned long n)
+{
+       unsigned long prefix  = vcpu->arch.sie_block->prefix;
 
-       if (guestsrc + n < guestsrc)
-               return -EFAULT;
+       if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
+               goto slowpath;
 
-       guestsrc += origin;
+       if ((guestsrc < prefix) && (guestsrc + n > prefix))
+               goto slowpath;
+
+       if ((guestsrc < prefix + 2 * PAGE_SIZE)
+           && (guestsrc + n > prefix + 2 * PAGE_SIZE))
+               goto slowpath;
+
+       if (guestsrc < 2 * PAGE_SIZE)
+               guestsrc += prefix;
+       else if ((guestsrc >= prefix) && (guestsrc < prefix + 2 * PAGE_SIZE))
+               guestsrc -= prefix;
 
-       return copy_from_user(to, (void __user *) guestsrc, n);
+       return __copy_from_guest_fast(vcpu, to, guestsrc, n);
+slowpath:
+       return __copy_from_guest_slow(vcpu, to, guestsrc, n);
 }
 #endif
index f7b6df4..c7c5189 100644 (file)
@@ -105,6 +105,7 @@ static intercept_handler_t instruction_handlers[256] = {
        [0xae] = kvm_s390_handle_sigp,
        [0xb2] = kvm_s390_handle_b2,
        [0xb7] = handle_lctl,
+       [0xe5] = kvm_s390_handle_e5,
        [0xeb] = handle_lctlg,
 };
 
@@ -159,22 +160,42 @@ static int handle_stop(struct kvm_vcpu *vcpu)
 
 static int handle_validity(struct kvm_vcpu *vcpu)
 {
+       unsigned long vmaddr;
        int viwhy = vcpu->arch.sie_block->ipb >> 16;
        int rc;
 
        vcpu->stat.exit_validity++;
-       if ((viwhy == 0x37) && (vcpu->arch.sie_block->prefix
-               <= kvm_s390_vcpu_get_memsize(vcpu) - 2*PAGE_SIZE)) {
-               rc = fault_in_pages_writeable((char __user *)
-                        vcpu->arch.sie_block->gmsor +
-                        vcpu->arch.sie_block->prefix,
-                        2*PAGE_SIZE);
-               if (rc)
+       if (viwhy == 0x37) {
+               vmaddr = gmap_fault(vcpu->arch.sie_block->prefix,
+                                   vcpu->arch.gmap);
+               if (IS_ERR_VALUE(vmaddr)) {
+                       rc = -EOPNOTSUPP;
+                       goto out;
+               }
+               rc = fault_in_pages_writeable((char __user *) vmaddr,
+                        PAGE_SIZE);
+               if (rc) {
+                       /* user will receive sigsegv, exit to user */
+                       rc = -EOPNOTSUPP;
+                       goto out;
+               }
+               vmaddr = gmap_fault(vcpu->arch.sie_block->prefix + PAGE_SIZE,
+                                   vcpu->arch.gmap);
+               if (IS_ERR_VALUE(vmaddr)) {
+                       rc = -EOPNOTSUPP;
+                       goto out;
+               }
+               rc = fault_in_pages_writeable((char __user *) vmaddr,
+                        PAGE_SIZE);
+               if (rc) {
                        /* user will receive sigsegv, exit to user */
                        rc = -EOPNOTSUPP;
+                       goto out;
+               }
        } else
                rc = -EOPNOTSUPP;
 
+out:
        if (rc)
                VCPU_EVENT(vcpu, 2, "unhandled validity intercept code %d",
                           viwhy);
index 35c21bf..c9aeb4b 100644 (file)
@@ -128,6 +128,10 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
                if (rc == -EFAULT)
                        exception = 1;
 
+               rc = put_guest_u16(vcpu, __LC_CPU_ADDRESS, inti->emerg.code);
+               if (rc == -EFAULT)
+                       exception = 1;
+
                rc = copy_to_guest(vcpu, __LC_EXT_OLD_PSW,
                         &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
                if (rc == -EFAULT)
index 67345ae..f17296e 100644 (file)
@@ -62,6 +62,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "instruction_chsc", VCPU_STAT(instruction_chsc) },
        { "instruction_stsi", VCPU_STAT(instruction_stsi) },
        { "instruction_stfl", VCPU_STAT(instruction_stfl) },
+       { "instruction_tprot", VCPU_STAT(instruction_tprot) },
        { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
        { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
        { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
@@ -189,7 +190,13 @@ int kvm_arch_init_vm(struct kvm *kvm)
        debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
        VM_EVENT(kvm, 3, "%s", "vm created");
 
+       kvm->arch.gmap = gmap_alloc(current->mm);
+       if (!kvm->arch.gmap)
+               goto out_nogmap;
+
        return 0;
+out_nogmap:
+       debug_unregister(kvm->arch.dbf);
 out_nodbf:
        free_page((unsigned long)(kvm->arch.sca));
 out_err:
@@ -234,11 +241,13 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        kvm_free_vcpus(kvm);
        free_page((unsigned long)(kvm->arch.sca));
        debug_unregister(kvm->arch.dbf);
+       gmap_free(kvm->arch.gmap);
 }
 
 /* Section: vcpu related */
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.gmap = vcpu->kvm->arch.gmap;
        return 0;
 }
 
@@ -284,8 +293,7 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-       atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
-       set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests);
+       atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
        vcpu->arch.sie_block->ecb   = 6;
        vcpu->arch.sie_block->eca   = 0xC1002001U;
        vcpu->arch.sie_block->fac   = (int) (long) facilities;
@@ -453,6 +461,7 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        local_irq_disable();
        kvm_guest_enter();
        local_irq_enable();
+       gmap_enable(vcpu->arch.gmap);
        VCPU_EVENT(vcpu, 6, "entering sie flags %x",
                   atomic_read(&vcpu->arch.sie_block->cpuflags));
        if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
@@ -461,6 +470,7 @@ static void __vcpu_run(struct kvm_vcpu *vcpu)
        }
        VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
                   vcpu->arch.sie_block->icptcode);
+       gmap_disable(vcpu->arch.gmap);
        local_irq_disable();
        kvm_guest_exit();
        local_irq_enable();
@@ -474,17 +484,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        sigset_t sigsaved;
 
 rerun_vcpu:
-       if (vcpu->requests)
-               if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
-                       kvm_s390_vcpu_set_mem(vcpu);
-
-       /* verify, that memory has been registered */
-       if (!vcpu->arch.sie_block->gmslm) {
-               vcpu_put(vcpu);
-               VCPU_EVENT(vcpu, 3, "%s", "no memory registered to run vcpu");
-               return -EINVAL;
-       }
-
        if (vcpu->sigset_active)
                sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
@@ -545,7 +544,7 @@ rerun_vcpu:
        return rc;
 }
 
-static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
+static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from,
                       unsigned long n, int prefix)
 {
        if (prefix)
@@ -562,7 +561,7 @@ static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
  */
 int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
 {
-       const unsigned char archmode = 1;
+       unsigned char archmode = 1;
        int prefix;
 
        if (addr == KVM_S390_STORE_STATUS_NOADDR) {
@@ -680,10 +679,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
        if (mem->guest_phys_addr)
                return -EINVAL;
 
-       if (mem->userspace_addr & (PAGE_SIZE - 1))
+       if (mem->userspace_addr & 0xffffful)
                return -EINVAL;
 
-       if (mem->memory_size & (PAGE_SIZE - 1))
+       if (mem->memory_size & 0xffffful)
                return -EINVAL;
 
        if (!user_alloc)
@@ -697,15 +696,14 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                                struct kvm_memory_slot old,
                                int user_alloc)
 {
-       int i;
-       struct kvm_vcpu *vcpu;
+       int rc;
 
-       /* request update of sie control block for all available vcpus */
-       kvm_for_each_vcpu(i, vcpu, kvm) {
-               if (test_and_set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
-                       continue;
-               kvm_s390_inject_sigp_stop(vcpu, ACTION_RELOADVCPU_ON_STOP);
-       }
+
+       rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
+               mem->guest_phys_addr, mem->memory_size);
+       if (rc)
+               printk(KERN_WARNING "kvm-s390: failed to commit memory region\n");
+       return;
 }
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
index a7b7586..99b0b75 100644 (file)
@@ -58,35 +58,9 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
 int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action);
 
-static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
-{
-       return vcpu->arch.sie_block->gmslm
-               - vcpu->arch.sie_block->gmsor
-               - VIRTIODESCSPACE + 1ul;
-}
-
-static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu)
-{
-       int idx;
-       struct kvm_memory_slot *mem;
-       struct kvm_memslots *memslots;
-
-       idx = srcu_read_lock(&vcpu->kvm->srcu);
-       memslots = kvm_memslots(vcpu->kvm);
-
-       mem = &memslots->memslots[0];
-
-       vcpu->arch.sie_block->gmsor = mem->userspace_addr;
-       vcpu->arch.sie_block->gmslm =
-               mem->userspace_addr +
-               (mem->npages << PAGE_SHIFT) +
-               VIRTIODESCSPACE - 1ul;
-
-       srcu_read_unlock(&vcpu->kvm->srcu, idx);
-}
-
 /* implemented in priv.c */
 int kvm_s390_handle_b2(struct kvm_vcpu *vcpu);
+int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
 
 /* implemented in sigp.c */
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
index 73c47bd..3916263 100644 (file)
@@ -326,3 +326,52 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
        }
        return -EOPNOTSUPP;
 }
+
+static int handle_tprot(struct kvm_vcpu *vcpu)
+{
+       int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
+       int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
+       int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
+       int disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
+       u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
+       u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
+       struct vm_area_struct *vma;
+
+       vcpu->stat.instruction_tprot++;
+
+       /* we only handle the Linux memory detection case:
+        * access key == 0
+        * guest DAT == off
+        * everything else goes to userspace. */
+       if (address2 & 0xf0)
+               return -EOPNOTSUPP;
+       if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
+               return -EOPNOTSUPP;
+
+
+       down_read(&current->mm->mmap_sem);
+       vma = find_vma(current->mm,
+                       (unsigned long) __guestaddr_to_user(vcpu, address1));
+       if (!vma) {
+               up_read(&current->mm->mmap_sem);
+               return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+       }
+
+       vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
+       if (!(vma->vm_flags & VM_WRITE) && (vma->vm_flags & VM_READ))
+               vcpu->arch.sie_block->gpsw.mask |= (1ul << 44);
+       if (!(vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_READ))
+               vcpu->arch.sie_block->gpsw.mask |= (2ul << 44);
+
+       up_read(&current->mm->mmap_sem);
+       return 0;
+}
+
+int kvm_s390_handle_e5(struct kvm_vcpu *vcpu)
+{
+       /* For e5xx... instructions we only handle TPROT */
+       if ((vcpu->arch.sie_block->ipa & 0x00ff) == 0x01)
+               return handle_tprot(vcpu);
+       return -EOPNOTSUPP;
+}
+
diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S
deleted file mode 100644 (file)
index 5faa1b1..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * sie64a.S - low level sie call
- *
- * Copyright IBM Corp. 2008,2010
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License (version 2 only)
- * as published by the Free Software Foundation.
- *
- *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- *              Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
- */
-
-#include <linux/errno.h>
-#include <asm/asm-offsets.h>
-#include <asm/setup.h>
-#include <asm/asm-offsets.h>
-#include <asm/ptrace.h>
-#include <asm/thread_info.h>
-
-_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
-
-/*
- * offsets into stackframe
- * SP_ = offsets into stack sie64 is called with
- * SPI_ = offsets into irq stack
- */
-SP_GREGS = __SF_EMPTY
-SP_HOOK  = __SF_EMPTY+8
-SP_GPP  = __SF_EMPTY+16
-SPI_PSW  = STACK_FRAME_OVERHEAD + __PT_PSW
-
-
-       .macro SPP newpp
-       tm      __LC_MACHINE_FLAGS+6,0x20       # MACHINE_FLAG_SPP
-       jz      0f
-       .insn   s,0xb2800000,\newpp
-0:
-       .endm
-
-sie_irq_handler:
-       SPP     __LC_CMF_HPP                    # set host id
-       larl    %r2,sie_inst
-       clg     %r2,SPI_PSW+8(0,%r15)           # intercepted sie
-       jne     1f
-       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
-       lg      %r2,__LC_THREAD_INFO            # pointer thread_info struct
-       tm      __TI_flags+7(%r2),_TIF_EXIT_SIE
-       jz      0f
-       larl    %r2,sie_exit                    # work pending, leave sie
-       stg     %r2,SPI_PSW+8(0,%r15)
-       br      %r14
-0:     larl    %r2,sie_reenter                 # re-enter with guest id
-       stg     %r2,SPI_PSW+8(0,%r15)
-1:     br      %r14
-
-/*
- * sie64a calling convention:
- * %r2 pointer to sie control block
- * %r3 guest register save area
- */
-       .globl  sie64a
-sie64a:
-       stg     %r3,SP_GREGS(%r15)              # save guest register save area
-       stmg    %r6,%r14,__SF_GPRS(%r15)        # save registers on entry
-       lgr     %r14,%r2                        # pointer to sie control block
-       larl    %r5,sie_irq_handler
-       stg     %r2,SP_GPP(%r15)
-       stg     %r5,SP_HOOK(%r15)               # save hook target
-       lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
-sie_reenter:
-       mvc     __LC_SIE_HOOK(8),SP_HOOK(%r15)
-       SPP     SP_GPP(%r15)                    # set guest id
-sie_inst:
-       sie     0(%r14)
-       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
-       SPP     __LC_CMF_HPP                    # set host id
-sie_exit:
-       lg      %r14,SP_GREGS(%r15)
-       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
-       lghi    %r2,0
-       lmg     %r6,%r14,__SF_GPRS(%r15)
-       br      %r14
-
-sie_err:
-       xc      __LC_SIE_HOOK(8),__LC_SIE_HOOK
-       SPP     __LC_CMF_HPP                    # set host id
-       lg      %r14,SP_GREGS(%r15)
-       stmg    %r0,%r13,0(%r14)                # save guest gprs 0-13
-       lghi    %r2,-EFAULT
-       lmg     %r6,%r14,__SF_GPRS(%r15)
-       br      %r14
-
-       .section __ex_table,"a"
-       .quad   sie_inst,sie_err
-       .quad   sie_exit,sie_err
-       .quad   sie_reenter,sie_err
-       .previous
index 702276f..d6a50c1 100644 (file)
@@ -189,10 +189,8 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
 
        /* make sure that the new value is valid memory */
        address = address & 0x7fffe000u;
-       if ((copy_from_user(&tmp, (void __user *)
-               (address + vcpu->arch.sie_block->gmsor) , 1)) ||
-          (copy_from_user(&tmp, (void __user *)(address +
-                       vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) {
+       if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
+          copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) {
                *reg |= SIGP_STAT_INVALID_PARAMETER;
                return 1; /* invalid parameter */
        }
index eb1df63..d321329 100644 (file)
@@ -1,5 +1,7 @@
 # S/390 __udiv_qrnnd
 
+#include <linux/linkage.h>
+
 # r2 : &__r
 # r3 : upper half of 64 bit word n
 # r4 : lower half of 64 bit word n
@@ -8,8 +10,7 @@
 # the quotient q is to be returned
 
        .text
-       .globl __udiv_qrnnd
-__udiv_qrnnd:
+ENTRY(__udiv_qrnnd)
        st    %r2,24(%r15)        # store pointer to reminder for later
        lr    %r0,%r3             # reload n
        lr    %r1,%r4
index 095f782..9564fc7 100644 (file)
@@ -303,9 +303,24 @@ static inline int do_exception(struct pt_regs *regs, int access,
        flags = FAULT_FLAG_ALLOW_RETRY;
        if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
                flags |= FAULT_FLAG_WRITE;
-retry:
        down_read(&mm->mmap_sem);
 
+#ifdef CONFIG_PGSTE
+       if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
+               address = gmap_fault(address,
+                                    (struct gmap *) S390_lowcore.gmap);
+               if (address == -EFAULT) {
+                       fault = VM_FAULT_BADMAP;
+                       goto out_up;
+               }
+               if (address == -ENOMEM) {
+                       fault = VM_FAULT_OOM;
+                       goto out_up;
+               }
+       }
+#endif
+
+retry:
        fault = VM_FAULT_BADMAP;
        vma = find_vma(mm, address);
        if (!vma)
@@ -356,6 +371,7 @@ retry:
                        /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
                         * of starvation. */
                        flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       down_read(&mm->mmap_sem);
                        goto retry;
                }
        }
index a4d856d..597bb2d 100644 (file)
@@ -35,7 +35,7 @@ int arch_prepare_hugepage(struct page *page)
        if (MACHINE_HAS_HPAGE)
                return 0;
 
-       ptep = (pte_t *) pte_alloc_one(&init_mm, address);
+       ptep = (pte_t *) pte_alloc_one(&init_mm, addr);
        if (!ptep)
                return -ENOMEM;
 
index 37a23c2..2adb239 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/quicklist.h>
 #include <linux/rcupdate.h>
+#include <linux/slab.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -133,30 +134,374 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
 }
 #endif
 
-static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+#ifdef CONFIG_PGSTE
+
+/**
+ * gmap_alloc - allocate a guest address space
+ * @mm: pointer to the parent mm_struct
+ *
+ * Returns a guest address space structure.
+ */
+struct gmap *gmap_alloc(struct mm_struct *mm)
 {
-       unsigned int old, new;
+       struct gmap *gmap;
+       struct page *page;
+       unsigned long *table;
 
-       do {
-               old = atomic_read(v);
-               new = old ^ bits;
-       } while (atomic_cmpxchg(v, old, new) != old);
-       return new;
+       gmap = kzalloc(sizeof(struct gmap), GFP_KERNEL);
+       if (!gmap)
+               goto out;
+       INIT_LIST_HEAD(&gmap->crst_list);
+       gmap->mm = mm;
+       page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+       if (!page)
+               goto out_free;
+       list_add(&page->lru, &gmap->crst_list);
+       table = (unsigned long *) page_to_phys(page);
+       crst_table_init(table, _REGION1_ENTRY_EMPTY);
+       gmap->table = table;
+       list_add(&gmap->list, &mm->context.gmap_list);
+       return gmap;
+
+out_free:
+       kfree(gmap);
+out:
+       return NULL;
 }
+EXPORT_SYMBOL_GPL(gmap_alloc);
 
-/*
- * page table entry allocation/free routines.
+static int gmap_unlink_segment(struct gmap *gmap, unsigned long *table)
+{
+       struct gmap_pgtable *mp;
+       struct gmap_rmap *rmap;
+       struct page *page;
+
+       if (*table & _SEGMENT_ENTRY_INV)
+               return 0;
+       page = pfn_to_page(*table >> PAGE_SHIFT);
+       mp = (struct gmap_pgtable *) page->index;
+       list_for_each_entry(rmap, &mp->mapper, list) {
+               if (rmap->entry != table)
+                       continue;
+               list_del(&rmap->list);
+               kfree(rmap);
+               break;
+       }
+       *table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+       return 1;
+}
+
+static void gmap_flush_tlb(struct gmap *gmap)
+{
+       if (MACHINE_HAS_IDTE)
+               __tlb_flush_idte((unsigned long) gmap->table |
+                                _ASCE_TYPE_REGION1);
+       else
+               __tlb_flush_global();
+}
+
+/**
+ * gmap_free - free a guest address space
+ * @gmap: pointer to the guest address space structure
  */
-#ifdef CONFIG_PGSTE
-static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
+void gmap_free(struct gmap *gmap)
+{
+       struct page *page, *next;
+       unsigned long *table;
+       int i;
+
+
+       /* Flush tlb. */
+       if (MACHINE_HAS_IDTE)
+               __tlb_flush_idte((unsigned long) gmap->table |
+                                _ASCE_TYPE_REGION1);
+       else
+               __tlb_flush_global();
+
+       /* Free all segment & region tables. */
+       down_read(&gmap->mm->mmap_sem);
+       list_for_each_entry_safe(page, next, &gmap->crst_list, lru) {
+               table = (unsigned long *) page_to_phys(page);
+               if ((*table & _REGION_ENTRY_TYPE_MASK) == 0)
+                       /* Remove gmap rmap structures for segment table. */
+                       for (i = 0; i < PTRS_PER_PMD; i++, table++)
+                               gmap_unlink_segment(gmap, table);
+               __free_pages(page, ALLOC_ORDER);
+       }
+       up_read(&gmap->mm->mmap_sem);
+       list_del(&gmap->list);
+       kfree(gmap);
+}
+EXPORT_SYMBOL_GPL(gmap_free);
+
+/**
+ * gmap_enable - switch primary space to the guest address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_enable(struct gmap *gmap)
+{
+       /* Load primary space page table origin. */
+       S390_lowcore.user_asce = _ASCE_TYPE_REGION1 | _ASCE_TABLE_LENGTH |
+                                _ASCE_USER_BITS | __pa(gmap->table);
+       asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) );
+       S390_lowcore.gmap = (unsigned long) gmap;
+}
+EXPORT_SYMBOL_GPL(gmap_enable);
+
+/**
+ * gmap_disable - switch back to the standard primary address space
+ * @gmap: pointer to the guest address space structure
+ */
+void gmap_disable(struct gmap *gmap)
+{
+       /* Load primary space page table origin. */
+       S390_lowcore.user_asce =
+               gmap->mm->context.asce_bits | __pa(gmap->mm->pgd);
+       asm volatile("lctlg 1,1,%0\n" : : "m" (S390_lowcore.user_asce) );
+       S390_lowcore.gmap = 0UL;
+}
+EXPORT_SYMBOL_GPL(gmap_disable);
+
+static int gmap_alloc_table(struct gmap *gmap,
+                              unsigned long *table, unsigned long init)
+{
+       struct page *page;
+       unsigned long *new;
+
+       page = alloc_pages(GFP_KERNEL, ALLOC_ORDER);
+       if (!page)
+               return -ENOMEM;
+       new = (unsigned long *) page_to_phys(page);
+       crst_table_init(new, init);
+       down_read(&gmap->mm->mmap_sem);
+       if (*table & _REGION_ENTRY_INV) {
+               list_add(&page->lru, &gmap->crst_list);
+               *table = (unsigned long) new | _REGION_ENTRY_LENGTH |
+                       (*table & _REGION_ENTRY_TYPE_MASK);
+       } else
+               __free_pages(page, ALLOC_ORDER);
+       up_read(&gmap->mm->mmap_sem);
+       return 0;
+}
+
+/**
+ * gmap_unmap_segment - unmap segment from the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @addr: address in the guest address space
+ * @len: length of the memory area to unmap
+ *
+ * Returns 0 if the unmap succeded, -EINVAL if not.
+ */
+int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)
+{
+       unsigned long *table;
+       unsigned long off;
+       int flush;
+
+       if ((to | len) & (PMD_SIZE - 1))
+               return -EINVAL;
+       if (len == 0 || to + len < to)
+               return -EINVAL;
+
+       flush = 0;
+       down_read(&gmap->mm->mmap_sem);
+       for (off = 0; off < len; off += PMD_SIZE) {
+               /* Walk the guest addr space page table */
+               table = gmap->table + (((to + off) >> 53) & 0x7ff);
+               if (*table & _REGION_ENTRY_INV)
+                       return 0;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+               table = table + (((to + off) >> 42) & 0x7ff);
+               if (*table & _REGION_ENTRY_INV)
+                       return 0;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+               table = table + (((to + off) >> 31) & 0x7ff);
+               if (*table & _REGION_ENTRY_INV)
+                       return 0;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+               table = table + (((to + off) >> 20) & 0x7ff);
+
+               /* Clear segment table entry in guest address space. */
+               flush |= gmap_unlink_segment(gmap, table);
+               *table = _SEGMENT_ENTRY_INV;
+       }
+       up_read(&gmap->mm->mmap_sem);
+       if (flush)
+               gmap_flush_tlb(gmap);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(gmap_unmap_segment);
+
+/**
+ * gmap_mmap_segment - map a segment to the guest address space
+ * @gmap: pointer to the guest address space structure
+ * @from: source address in the parent address space
+ * @to: target address in the guest address space
+ *
+ * Returns 0 if the mmap succeded, -EINVAL or -ENOMEM if not.
+ */
+int gmap_map_segment(struct gmap *gmap, unsigned long from,
+                    unsigned long to, unsigned long len)
+{
+       unsigned long *table;
+       unsigned long off;
+       int flush;
+
+       if ((from | to | len) & (PMD_SIZE - 1))
+               return -EINVAL;
+       if (len == 0 || from + len > PGDIR_SIZE ||
+           from + len < from || to + len < to)
+               return -EINVAL;
+
+       flush = 0;
+       down_read(&gmap->mm->mmap_sem);
+       for (off = 0; off < len; off += PMD_SIZE) {
+               /* Walk the gmap address space page table */
+               table = gmap->table + (((to + off) >> 53) & 0x7ff);
+               if ((*table & _REGION_ENTRY_INV) &&
+                   gmap_alloc_table(gmap, table, _REGION2_ENTRY_EMPTY))
+                       goto out_unmap;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+               table = table + (((to + off) >> 42) & 0x7ff);
+               if ((*table & _REGION_ENTRY_INV) &&
+                   gmap_alloc_table(gmap, table, _REGION3_ENTRY_EMPTY))
+                       goto out_unmap;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+               table = table + (((to + off) >> 31) & 0x7ff);
+               if ((*table & _REGION_ENTRY_INV) &&
+                   gmap_alloc_table(gmap, table, _SEGMENT_ENTRY_EMPTY))
+                       goto out_unmap;
+               table = (unsigned long *) (*table & _REGION_ENTRY_ORIGIN);
+               table = table + (((to + off) >> 20) & 0x7ff);
+
+               /* Store 'from' address in an invalid segment table entry. */
+               flush |= gmap_unlink_segment(gmap, table);
+               *table = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | (from + off);
+       }
+       up_read(&gmap->mm->mmap_sem);
+       if (flush)
+               gmap_flush_tlb(gmap);
+       return 0;
+
+out_unmap:
+       up_read(&gmap->mm->mmap_sem);
+       gmap_unmap_segment(gmap, to, len);
+       return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(gmap_map_segment);
+
+unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
+{
+       unsigned long *table, vmaddr, segment;
+       struct mm_struct *mm;
+       struct gmap_pgtable *mp;
+       struct gmap_rmap *rmap;
+       struct vm_area_struct *vma;
+       struct page *page;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+
+       current->thread.gmap_addr = address;
+       mm = gmap->mm;
+       /* Walk the gmap address space page table */
+       table = gmap->table + ((address >> 53) & 0x7ff);
+       if (unlikely(*table & _REGION_ENTRY_INV))
+               return -EFAULT;
+       table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       table = table + ((address >> 42) & 0x7ff);
+       if (unlikely(*table & _REGION_ENTRY_INV))
+               return -EFAULT;
+       table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       table = table + ((address >> 31) & 0x7ff);
+       if (unlikely(*table & _REGION_ENTRY_INV))
+               return -EFAULT;
+       table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       table = table + ((address >> 20) & 0x7ff);
+
+       /* Convert the gmap address to an mm address. */
+       segment = *table;
+       if (likely(!(segment & _SEGMENT_ENTRY_INV))) {
+               page = pfn_to_page(segment >> PAGE_SHIFT);
+               mp = (struct gmap_pgtable *) page->index;
+               return mp->vmaddr | (address & ~PMD_MASK);
+       } else if (segment & _SEGMENT_ENTRY_RO) {
+               vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
+               vma = find_vma(mm, vmaddr);
+               if (!vma || vma->vm_start > vmaddr)
+                       return -EFAULT;
+
+               /* Walk the parent mm page table */
+               pgd = pgd_offset(mm, vmaddr);
+               pud = pud_alloc(mm, pgd, vmaddr);
+               if (!pud)
+                       return -ENOMEM;
+               pmd = pmd_alloc(mm, pud, vmaddr);
+               if (!pmd)
+                       return -ENOMEM;
+               if (!pmd_present(*pmd) &&
+                   __pte_alloc(mm, vma, pmd, vmaddr))
+                       return -ENOMEM;
+               /* pmd now points to a valid segment table entry. */
+               rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
+               if (!rmap)
+                       return -ENOMEM;
+               /* Link gmap segment table entry location to page table. */
+               page = pmd_page(*pmd);
+               mp = (struct gmap_pgtable *) page->index;
+               rmap->entry = table;
+               list_add(&rmap->list, &mp->mapper);
+               /* Set gmap segment table entry to page table. */
+               *table = pmd_val(*pmd) & PAGE_MASK;
+               return vmaddr | (address & ~PMD_MASK);
+       }
+       return -EFAULT;
+
+}
+EXPORT_SYMBOL_GPL(gmap_fault);
+
+void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
+{
+       struct gmap_rmap *rmap, *next;
+       struct gmap_pgtable *mp;
+       struct page *page;
+       int flush;
+
+       flush = 0;
+       spin_lock(&mm->page_table_lock);
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       mp = (struct gmap_pgtable *) page->index;
+       list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
+               *rmap->entry =
+                       _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+               list_del(&rmap->list);
+               kfree(rmap);
+               flush = 1;
+       }
+       spin_unlock(&mm->page_table_lock);
+       if (flush)
+               __tlb_flush_global();
+}
+
+static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
+                                                   unsigned long vmaddr)
 {
        struct page *page;
        unsigned long *table;
+       struct gmap_pgtable *mp;
 
        page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
        if (!page)
                return NULL;
+       mp = kmalloc(sizeof(*mp), GFP_KERNEL|__GFP_REPEAT);
+       if (!mp) {
+               __free_page(page);
+               return NULL;
+       }
        pgtable_page_ctor(page);
+       mp->vmaddr = vmaddr & PMD_MASK;
+       INIT_LIST_HEAD(&mp->mapper);
+       page->index = (unsigned long) mp;
        atomic_set(&page->_mapcount, 3);
        table = (unsigned long *) page_to_phys(page);
        clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE/2);
@@ -167,24 +512,57 @@ static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm)
 static inline void page_table_free_pgste(unsigned long *table)
 {
        struct page *page;
+       struct gmap_pgtable *mp;
 
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       mp = (struct gmap_pgtable *) page->index;
+       BUG_ON(!list_empty(&mp->mapper));
        pgtable_page_ctor(page);
        atomic_set(&page->_mapcount, -1);
+       kfree(mp);
        __free_page(page);
 }
-#endif
 
-unsigned long *page_table_alloc(struct mm_struct *mm)
+#else /* CONFIG_PGSTE */
+
+static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
+                                                   unsigned long vmaddr)
+{
+}
+
+static inline void page_table_free_pgste(unsigned long *table)
+{
+}
+
+static inline void gmap_unmap_notifier(struct mm_struct *mm,
+                                         unsigned long *table)
+{
+}
+
+#endif /* CONFIG_PGSTE */
+
+static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
+{
+       unsigned int old, new;
+
+       do {
+               old = atomic_read(v);
+               new = old ^ bits;
+       } while (atomic_cmpxchg(v, old, new) != old);
+       return new;
+}
+
+/*
+ * page table entry allocation/free routines.
+ */
+unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
 {
        struct page *page;
        unsigned long *table;
        unsigned int mask, bit;
 
-#ifdef CONFIG_PGSTE
        if (mm_has_pgste(mm))
-               return page_table_alloc_pgste(mm);
-#endif
+               return page_table_alloc_pgste(mm, vmaddr);
        /* Allocate fragments of a 4K page as 1K/2K page table */
        spin_lock_bh(&mm->context.list_lock);
        mask = FRAG_MASK;
@@ -222,10 +600,10 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
        struct page *page;
        unsigned int bit, mask;
 
-#ifdef CONFIG_PGSTE
-       if (mm_has_pgste(mm))
+       if (mm_has_pgste(mm)) {
+               gmap_unmap_notifier(mm, table);
                return page_table_free_pgste(table);
-#endif
+       }
        /* Free 1K/2K page table fragment of a 4K page */
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        bit = 1 << ((__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t)));
@@ -249,10 +627,8 @@ static void __page_table_free_rcu(void *table, unsigned bit)
 {
        struct page *page;
 
-#ifdef CONFIG_PGSTE
        if (bit == FRAG_MASK)
                return page_table_free_pgste(table);
-#endif
        /* Free 1K/2K page table fragment of a 4K page */
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        if (atomic_xor_bits(&page->_mapcount, bit) == 0) {
@@ -269,13 +645,12 @@ void page_table_free_rcu(struct mmu_gather *tlb, unsigned long *table)
        unsigned int bit, mask;
 
        mm = tlb->mm;
-#ifdef CONFIG_PGSTE
        if (mm_has_pgste(mm)) {
+               gmap_unmap_notifier(mm, table);
                table = (unsigned long *) (__pa(table) | FRAG_MASK);
                tlb_remove_table(tlb, table);
                return;
        }
-#endif
        bit = 1 << ((__pa(table) & ~PAGE_MASK) / (PTRS_PER_PTE*sizeof(pte_t)));
        page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
        spin_lock_bh(&mm->context.list_lock);
index 8c1970d..781ff51 100644 (file)
@@ -61,12 +61,12 @@ static inline pmd_t *vmem_pmd_alloc(void)
        return pmd;
 }
 
-static pte_t __ref *vmem_pte_alloc(void)
+static pte_t __ref *vmem_pte_alloc(unsigned long address)
 {
        pte_t *pte;
 
        if (slab_is_available())
-               pte = (pte_t *) page_table_alloc(&init_mm);
+               pte = (pte_t *) page_table_alloc(&init_mm, address);
        else
                pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
        if (!pte)
@@ -120,7 +120,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                }
 #endif
                if (pmd_none(*pm_dir)) {
-                       pt_dir = vmem_pte_alloc();
+                       pt_dir = vmem_pte_alloc(address);
                        if (!pt_dir)
                                goto out;
                        pmd_populate(&init_mm, pm_dir, pt_dir);
@@ -205,7 +205,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node)
 
                pm_dir = pmd_offset(pu_dir, address);
                if (pmd_none(*pm_dir)) {
-                       pt_dir = vmem_pte_alloc();
+                       pt_dir = vmem_pte_alloc(address);
                        if (!pt_dir)
                                goto out;
                        pmd_populate(&init_mm, pm_dir, pt_dir);
index 86b6f1c..432444a 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/hdreg.h>
 #include <linux/async.h>
 #include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include <asm/ccwdev.h>
 #include <asm/ebcdic.h>
@@ -45,6 +47,7 @@
  * SECTION: exported variables of dasd.c
  */
 debug_info_t *dasd_debug_area;
+static struct dentry *dasd_debugfs_root_entry;
 struct dasd_discipline *dasd_diag_discipline_pointer;
 void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 
@@ -71,6 +74,8 @@ static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
 static void dasd_device_timeout(unsigned long);
 static void dasd_block_timeout(unsigned long);
 static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *);
+static void dasd_profile_init(struct dasd_profile *, struct dentry *);
+static void dasd_profile_exit(struct dasd_profile *);
 
 /*
  * SECTION: Operations on the device structure.
@@ -121,7 +126,7 @@ struct dasd_device *dasd_alloc_device(void)
        device->state = DASD_STATE_NEW;
        device->target = DASD_STATE_NEW;
        mutex_init(&device->state_mutex);
-
+       spin_lock_init(&device->profile.lock);
        return device;
 }
 
@@ -159,6 +164,7 @@ struct dasd_block *dasd_alloc_block(void)
        init_timer(&block->timer);
        block->timer.function = dasd_block_timeout;
        block->timer.data = (unsigned long) block;
+       spin_lock_init(&block->profile.lock);
 
        return block;
 }
@@ -222,19 +228,44 @@ static int dasd_state_known_to_new(struct dasd_device *device)
        return 0;
 }
 
+static struct dentry *dasd_debugfs_setup(const char *name,
+                                        struct dentry *base_dentry)
+{
+       struct dentry *pde;
+
+       if (!base_dentry)
+               return NULL;
+       pde = debugfs_create_dir(name, base_dentry);
+       if (!pde || IS_ERR(pde))
+               return NULL;
+       return pde;
+}
+
 /*
  * Request the irq line for the device.
  */
 static int dasd_state_known_to_basic(struct dasd_device *device)
 {
+       struct dasd_block *block = device->block;
        int rc;
 
        /* Allocate and register gendisk structure. */
-       if (device->block) {
-               rc = dasd_gendisk_alloc(device->block);
+       if (block) {
+               rc = dasd_gendisk_alloc(block);
                if (rc)
                        return rc;
-       }
+               block->debugfs_dentry =
+                       dasd_debugfs_setup(block->gdp->disk_name,
+                                          dasd_debugfs_root_entry);
+               dasd_profile_init(&block->profile, block->debugfs_dentry);
+               if (dasd_global_profile_level == DASD_PROFILE_ON)
+                       dasd_profile_on(&device->block->profile);
+       }
+       device->debugfs_dentry =
+               dasd_debugfs_setup(dev_name(&device->cdev->dev),
+                                  dasd_debugfs_root_entry);
+       dasd_profile_init(&device->profile, device->debugfs_dentry);
+
        /* register 'device' debug area, used for all DBF_DEV_XXX calls */
        device->debug_area = debug_register(dev_name(&device->cdev->dev), 4, 1,
                                            8 * sizeof(long));
@@ -253,6 +284,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
 {
        int rc;
        if (device->block) {
+               dasd_profile_exit(&device->block->profile);
+               if (device->block->debugfs_dentry)
+                       debugfs_remove(device->block->debugfs_dentry);
                dasd_gendisk_free(device->block);
                dasd_block_clear_timer(device->block);
        }
@@ -260,6 +294,9 @@ static int dasd_state_basic_to_known(struct dasd_device *device)
        if (rc)
                return rc;
        dasd_device_clear_timer(device);
+       dasd_profile_exit(&device->profile);
+       if (device->debugfs_dentry)
+               debugfs_remove(device->debugfs_dentry);
 
        DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
        if (device->debug_area != NULL) {
@@ -609,21 +646,13 @@ void dasd_enable_device(struct dasd_device *device)
 /*
  * SECTION: device operation (interrupt handler, start i/o, term i/o ...)
  */
-#ifdef CONFIG_DASD_PROFILE
 
-struct dasd_profile_info_t dasd_global_profile;
-unsigned int dasd_profile_level = DASD_PROFILE_OFF;
+unsigned int dasd_global_profile_level = DASD_PROFILE_OFF;
 
-/*
- * Increments counter in global and local profiling structures.
- */
-#define dasd_profile_counter(value, counter, block) \
-{ \
-       int index; \
-       for (index = 0; index < 31 && value >> (2+index); index++); \
-       dasd_global_profile.counter[index]++; \
-       block->profile.counter[index]++; \
-}
+#ifdef CONFIG_DASD_PROFILE
+struct dasd_profile_info dasd_global_profile_data;
+static struct dentry *dasd_global_profile_dentry;
+static struct dentry *dasd_debugfs_global_entry;
 
 /*
  * Add profiling information for cqr before execution.
@@ -634,30 +663,121 @@ static void dasd_profile_start(struct dasd_block *block,
 {
        struct list_head *l;
        unsigned int counter;
-
-       if (dasd_profile_level != DASD_PROFILE_ON)
-               return;
+       struct dasd_device *device;
 
        /* count the length of the chanq for statistics */
        counter = 0;
-       list_for_each(l, &block->ccw_queue)
-               if (++counter >= 31)
-                       break;
-       dasd_global_profile.dasd_io_nr_req[counter]++;
-       block->profile.dasd_io_nr_req[counter]++;
+       if (dasd_global_profile_level || block->profile.data)
+               list_for_each(l, &block->ccw_queue)
+                       if (++counter >= 31)
+                               break;
+
+       if (dasd_global_profile_level) {
+               dasd_global_profile_data.dasd_io_nr_req[counter]++;
+               if (rq_data_dir(req) == READ)
+                       dasd_global_profile_data.dasd_read_nr_req[counter]++;
+       }
+
+       spin_lock(&block->profile.lock);
+       if (block->profile.data)
+               block->profile.data->dasd_io_nr_req[counter]++;
+               if (rq_data_dir(req) == READ)
+                       block->profile.data->dasd_read_nr_req[counter]++;
+       spin_unlock(&block->profile.lock);
+
+       /*
+        * We count the request for the start device, even though it may run on
+        * some other device due to error recovery. This way we make sure that
+        * we count each request only once.
+        */
+       device = cqr->startdev;
+       if (device->profile.data) {
+               counter = 1; /* request is not yet queued on the start device */
+               list_for_each(l, &device->ccw_queue)
+                       if (++counter >= 31)
+                               break;
+       }
+       spin_lock(&device->profile.lock);
+       if (device->profile.data) {
+               device->profile.data->dasd_io_nr_req[counter]++;
+               if (rq_data_dir(req) == READ)
+                       device->profile.data->dasd_read_nr_req[counter]++;
+       }
+       spin_unlock(&device->profile.lock);
 }
 
 /*
  * Add profiling information for cqr after execution.
  */
+
+#define dasd_profile_counter(value, index)                        \
+{                                                                 \
+       for (index = 0; index < 31 && value >> (2+index); index++) \
+               ;                                                  \
+}
+
+static void dasd_profile_end_add_data(struct dasd_profile_info *data,
+                                     int is_alias,
+                                     int is_tpm,
+                                     int is_read,
+                                     long sectors,
+                                     int sectors_ind,
+                                     int tottime_ind,
+                                     int tottimeps_ind,
+                                     int strtime_ind,
+                                     int irqtime_ind,
+                                     int irqtimeps_ind,
+                                     int endtime_ind)
+{
+       /* in case of an overflow, reset the whole profile */
+       if (data->dasd_io_reqs == UINT_MAX) {
+                       memset(data, 0, sizeof(*data));
+                       getnstimeofday(&data->starttod);
+       }
+       data->dasd_io_reqs++;
+       data->dasd_io_sects += sectors;
+       if (is_alias)
+               data->dasd_io_alias++;
+       if (is_tpm)
+               data->dasd_io_tpm++;
+
+       data->dasd_io_secs[sectors_ind]++;
+       data->dasd_io_times[tottime_ind]++;
+       data->dasd_io_timps[tottimeps_ind]++;
+       data->dasd_io_time1[strtime_ind]++;
+       data->dasd_io_time2[irqtime_ind]++;
+       data->dasd_io_time2ps[irqtimeps_ind]++;
+       data->dasd_io_time3[endtime_ind]++;
+
+       if (is_read) {
+               data->dasd_read_reqs++;
+               data->dasd_read_sects += sectors;
+               if (is_alias)
+                       data->dasd_read_alias++;
+               if (is_tpm)
+                       data->dasd_read_tpm++;
+               data->dasd_read_secs[sectors_ind]++;
+               data->dasd_read_times[tottime_ind]++;
+               data->dasd_read_time1[strtime_ind]++;
+               data->dasd_read_time2[irqtime_ind]++;
+               data->dasd_read_time3[endtime_ind]++;
+       }
+}
+
 static void dasd_profile_end(struct dasd_block *block,
                             struct dasd_ccw_req *cqr,
                             struct request *req)
 {
        long strtime, irqtime, endtime, tottime;        /* in microseconds */
        long tottimeps, sectors;
+       struct dasd_device *device;
+       int sectors_ind, tottime_ind, tottimeps_ind, strtime_ind;
+       int irqtime_ind, irqtimeps_ind, endtime_ind;
 
-       if (dasd_profile_level != DASD_PROFILE_ON)
+       device = cqr->startdev;
+       if (!(dasd_global_profile_level ||
+             block->profile.data ||
+             device->profile.data))
                return;
 
        sectors = blk_rq_sectors(req);
@@ -672,29 +792,392 @@ static void dasd_profile_end(struct dasd_block *block,
        tottime = ((cqr->endclk - cqr->buildclk) >> 12);
        tottimeps = tottime / sectors;
 
-       if (!dasd_global_profile.dasd_io_reqs)
-               memset(&dasd_global_profile, 0,
-                      sizeof(struct dasd_profile_info_t));
-       dasd_global_profile.dasd_io_reqs++;
-       dasd_global_profile.dasd_io_sects += sectors;
-
-       if (!block->profile.dasd_io_reqs)
-               memset(&block->profile, 0,
-                      sizeof(struct dasd_profile_info_t));
-       block->profile.dasd_io_reqs++;
-       block->profile.dasd_io_sects += sectors;
-
-       dasd_profile_counter(sectors, dasd_io_secs, block);
-       dasd_profile_counter(tottime, dasd_io_times, block);
-       dasd_profile_counter(tottimeps, dasd_io_timps, block);
-       dasd_profile_counter(strtime, dasd_io_time1, block);
-       dasd_profile_counter(irqtime, dasd_io_time2, block);
-       dasd_profile_counter(irqtime / sectors, dasd_io_time2ps, block);
-       dasd_profile_counter(endtime, dasd_io_time3, block);
+       dasd_profile_counter(sectors, sectors_ind);
+       dasd_profile_counter(tottime, tottime_ind);
+       dasd_profile_counter(tottimeps, tottimeps_ind);
+       dasd_profile_counter(strtime, strtime_ind);
+       dasd_profile_counter(irqtime, irqtime_ind);
+       dasd_profile_counter(irqtime / sectors, irqtimeps_ind);
+       dasd_profile_counter(endtime, endtime_ind);
+
+       if (dasd_global_profile_level) {
+               dasd_profile_end_add_data(&dasd_global_profile_data,
+                                         cqr->startdev != block->base,
+                                         cqr->cpmode == 1,
+                                         rq_data_dir(req) == READ,
+                                         sectors, sectors_ind, tottime_ind,
+                                         tottimeps_ind, strtime_ind,
+                                         irqtime_ind, irqtimeps_ind,
+                                         endtime_ind);
+       }
+
+       spin_lock(&block->profile.lock);
+       if (block->profile.data)
+               dasd_profile_end_add_data(block->profile.data,
+                                         cqr->startdev != block->base,
+                                         cqr->cpmode == 1,
+                                         rq_data_dir(req) == READ,
+                                         sectors, sectors_ind, tottime_ind,
+                                         tottimeps_ind, strtime_ind,
+                                         irqtime_ind, irqtimeps_ind,
+                                         endtime_ind);
+       spin_unlock(&block->profile.lock);
+
+       spin_lock(&device->profile.lock);
+       if (device->profile.data)
+               dasd_profile_end_add_data(device->profile.data,
+                                         cqr->startdev != block->base,
+                                         cqr->cpmode == 1,
+                                         rq_data_dir(req) == READ,
+                                         sectors, sectors_ind, tottime_ind,
+                                         tottimeps_ind, strtime_ind,
+                                         irqtime_ind, irqtimeps_ind,
+                                         endtime_ind);
+       spin_unlock(&device->profile.lock);
+}
+
+void dasd_profile_reset(struct dasd_profile *profile)
+{
+       struct dasd_profile_info *data;
+
+       spin_lock_bh(&profile->lock);
+       data = profile->data;
+       if (!data) {
+               spin_unlock_bh(&profile->lock);
+               return;
+       }
+       memset(data, 0, sizeof(*data));
+       getnstimeofday(&data->starttod);
+       spin_unlock_bh(&profile->lock);
+}
+
+void dasd_global_profile_reset(void)
+{
+       memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data));
+       getnstimeofday(&dasd_global_profile_data.starttod);
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+       struct dasd_profile_info *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       spin_lock_bh(&profile->lock);
+       if (profile->data) {
+               spin_unlock_bh(&profile->lock);
+               kfree(data);
+               return 0;
+       }
+       getnstimeofday(&data->starttod);
+       profile->data = data;
+       spin_unlock_bh(&profile->lock);
+       return 0;
+}
+
+void dasd_profile_off(struct dasd_profile *profile)
+{
+       spin_lock_bh(&profile->lock);
+       kfree(profile->data);
+       profile->data = NULL;
+       spin_unlock_bh(&profile->lock);
+}
+
+char *dasd_get_user_string(const char __user *user_buf, size_t user_len)
+{
+       char *buffer;
+
+       buffer = kmalloc(user_len + 1, GFP_KERNEL);
+       if (buffer == NULL)
+               return ERR_PTR(-ENOMEM);
+       if (copy_from_user(buffer, user_buf, user_len) != 0) {
+               kfree(buffer);
+               return ERR_PTR(-EFAULT);
+       }
+       /* got the string, now strip linefeed. */
+       if (buffer[user_len - 1] == '\n')
+               buffer[user_len - 1] = 0;
+       else
+               buffer[user_len] = 0;
+       return buffer;
 }
+
+static ssize_t dasd_stats_write(struct file *file,
+                               const char __user *user_buf,
+                               size_t user_len, loff_t *pos)
+{
+       char *buffer, *str;
+       int rc;
+       struct seq_file *m = (struct seq_file *)file->private_data;
+       struct dasd_profile *prof = m->private;
+
+       if (user_len > 65536)
+               user_len = 65536;
+       buffer = dasd_get_user_string(user_buf, user_len);
+       if (IS_ERR(buffer))
+               return PTR_ERR(buffer);
+
+       str = skip_spaces(buffer);
+       rc = user_len;
+       if (strncmp(str, "reset", 5) == 0) {
+               dasd_profile_reset(prof);
+       } else if (strncmp(str, "on", 2) == 0) {
+               rc = dasd_profile_on(prof);
+               if (!rc)
+                       rc = user_len;
+       } else if (strncmp(str, "off", 3) == 0) {
+               dasd_profile_off(prof);
+       } else
+               rc = -EINVAL;
+       kfree(buffer);
+       return rc;
+}
+
+static void dasd_stats_array(struct seq_file *m, unsigned int *array)
+{
+       int i;
+
+       for (i = 0; i < 32; i++)
+               seq_printf(m, "%u ", array[i]);
+       seq_putc(m, '\n');
+}
+
+static void dasd_stats_seq_print(struct seq_file *m,
+                                struct dasd_profile_info *data)
+{
+       seq_printf(m, "start_time %ld.%09ld\n",
+                  data->starttod.tv_sec, data->starttod.tv_nsec);
+       seq_printf(m, "total_requests %u\n", data->dasd_io_reqs);
+       seq_printf(m, "total_sectors %u\n", data->dasd_io_sects);
+       seq_printf(m, "total_pav %u\n", data->dasd_io_alias);
+       seq_printf(m, "total_hpf %u\n", data->dasd_io_tpm);
+       seq_printf(m, "histogram_sectors ");
+       dasd_stats_array(m, data->dasd_io_secs);
+       seq_printf(m, "histogram_io_times ");
+       dasd_stats_array(m, data->dasd_io_times);
+       seq_printf(m, "histogram_io_times_weighted ");
+       dasd_stats_array(m, data->dasd_io_timps);
+       seq_printf(m, "histogram_time_build_to_ssch ");
+       dasd_stats_array(m, data->dasd_io_time1);
+       seq_printf(m, "histogram_time_ssch_to_irq ");
+       dasd_stats_array(m, data->dasd_io_time2);
+       seq_printf(m, "histogram_time_ssch_to_irq_weighted ");
+       dasd_stats_array(m, data->dasd_io_time2ps);
+       seq_printf(m, "histogram_time_irq_to_end ");
+       dasd_stats_array(m, data->dasd_io_time3);
+       seq_printf(m, "histogram_ccw_queue_length ");
+       dasd_stats_array(m, data->dasd_io_nr_req);
+       seq_printf(m, "total_read_requests %u\n", data->dasd_read_reqs);
+       seq_printf(m, "total_read_sectors %u\n", data->dasd_read_sects);
+       seq_printf(m, "total_read_pav %u\n", data->dasd_read_alias);
+       seq_printf(m, "total_read_hpf %u\n", data->dasd_read_tpm);
+       seq_printf(m, "histogram_read_sectors ");
+       dasd_stats_array(m, data->dasd_read_secs);
+       seq_printf(m, "histogram_read_times ");
+       dasd_stats_array(m, data->dasd_read_times);
+       seq_printf(m, "histogram_read_time_build_to_ssch ");
+       dasd_stats_array(m, data->dasd_read_time1);
+       seq_printf(m, "histogram_read_time_ssch_to_irq ");
+       dasd_stats_array(m, data->dasd_read_time2);
+       seq_printf(m, "histogram_read_time_irq_to_end ");
+       dasd_stats_array(m, data->dasd_read_time3);
+       seq_printf(m, "histogram_read_ccw_queue_length ");
+       dasd_stats_array(m, data->dasd_read_nr_req);
+}
+
+static int dasd_stats_show(struct seq_file *m, void *v)
+{
+       struct dasd_profile *profile;
+       struct dasd_profile_info *data;
+
+       profile = m->private;
+       spin_lock_bh(&profile->lock);
+       data = profile->data;
+       if (!data) {
+               spin_unlock_bh(&profile->lock);
+               seq_printf(m, "disabled\n");
+               return 0;
+       }
+       dasd_stats_seq_print(m, data);
+       spin_unlock_bh(&profile->lock);
+       return 0;
+}
+
+static int dasd_stats_open(struct inode *inode, struct file *file)
+{
+       struct dasd_profile *profile = inode->i_private;
+       return single_open(file, dasd_stats_show, profile);
+}
+
+static const struct file_operations dasd_stats_raw_fops = {
+       .owner          = THIS_MODULE,
+       .open           = dasd_stats_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = dasd_stats_write,
+};
+
+static ssize_t dasd_stats_global_write(struct file *file,
+                                      const char __user *user_buf,
+                                      size_t user_len, loff_t *pos)
+{
+       char *buffer, *str;
+       ssize_t rc;
+
+       if (user_len > 65536)
+               user_len = 65536;
+       buffer = dasd_get_user_string(user_buf, user_len);
+       if (IS_ERR(buffer))
+               return PTR_ERR(buffer);
+       str = skip_spaces(buffer);
+       rc = user_len;
+       if (strncmp(str, "reset", 5) == 0) {
+               dasd_global_profile_reset();
+       } else if (strncmp(str, "on", 2) == 0) {
+               dasd_global_profile_reset();
+               dasd_global_profile_level = DASD_PROFILE_GLOBAL_ONLY;
+       } else if (strncmp(str, "off", 3) == 0) {
+               dasd_global_profile_level = DASD_PROFILE_OFF;
+       } else
+               rc = -EINVAL;
+       kfree(buffer);
+       return rc;
+}
+
+static int dasd_stats_global_show(struct seq_file *m, void *v)
+{
+       if (!dasd_global_profile_level) {
+               seq_printf(m, "disabled\n");
+               return 0;
+       }
+       dasd_stats_seq_print(m, &dasd_global_profile_data);
+       return 0;
+}
+
+static int dasd_stats_global_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dasd_stats_global_show, NULL);
+}
+
+static const struct file_operations dasd_stats_global_fops = {
+       .owner          = THIS_MODULE,
+       .open           = dasd_stats_global_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = dasd_stats_global_write,
+};
+
+static void dasd_profile_init(struct dasd_profile *profile,
+                             struct dentry *base_dentry)
+{
+       mode_t mode;
+       struct dentry *pde;
+
+       if (!base_dentry)
+               return;
+       profile->dentry = NULL;
+       profile->data = NULL;
+       mode = (S_IRUSR | S_IWUSR | S_IFREG);
+       pde = debugfs_create_file("statistics", mode, base_dentry,
+                                 profile, &dasd_stats_raw_fops);
+       if (pde && !IS_ERR(pde))
+               profile->dentry = pde;
+       return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+       dasd_profile_off(profile);
+       if (profile->dentry) {
+               debugfs_remove(profile->dentry);
+               profile->dentry = NULL;
+       }
+}
+
+static void dasd_statistics_removeroot(void)
+{
+       dasd_global_profile_level = DASD_PROFILE_OFF;
+       if (dasd_global_profile_dentry) {
+               debugfs_remove(dasd_global_profile_dentry);
+               dasd_global_profile_dentry = NULL;
+       }
+       if (dasd_debugfs_global_entry)
+               debugfs_remove(dasd_debugfs_global_entry);
+       if (dasd_debugfs_root_entry)
+               debugfs_remove(dasd_debugfs_root_entry);
+}
+
+static void dasd_statistics_createroot(void)
+{
+       mode_t mode;
+       struct dentry *pde;
+
+       dasd_debugfs_root_entry = NULL;
+       dasd_debugfs_global_entry = NULL;
+       dasd_global_profile_dentry = NULL;
+       pde = debugfs_create_dir("dasd", NULL);
+       if (!pde || IS_ERR(pde))
+               goto error;
+       dasd_debugfs_root_entry = pde;
+       pde = debugfs_create_dir("global", dasd_debugfs_root_entry);
+       if (!pde || IS_ERR(pde))
+               goto error;
+       dasd_debugfs_global_entry = pde;
+
+       mode = (S_IRUSR | S_IWUSR | S_IFREG);
+       pde = debugfs_create_file("statistics", mode, dasd_debugfs_global_entry,
+                                 NULL, &dasd_stats_global_fops);
+       if (!pde || IS_ERR(pde))
+               goto error;
+       dasd_global_profile_dentry = pde;
+       return;
+
+error:
+       DBF_EVENT(DBF_ERR, "%s",
+                 "Creation of the dasd debugfs interface failed");
+       dasd_statistics_removeroot();
+       return;
+}
+
 #else
 #define dasd_profile_start(block, cqr, req) do {} while (0)
 #define dasd_profile_end(block, cqr, req) do {} while (0)
+
+static void dasd_statistics_createroot(void)
+{
+       return;
+}
+
+static void dasd_statistics_removeroot(void)
+{
+       return;
+}
+
+int dasd_stats_generic_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "Statistics are not activated in this kernel\n");
+       return 0;
+}
+
+static void dasd_profile_init(struct dasd_profile *profile,
+                             struct dentry *base_dentry)
+{
+       return;
+}
+
+static void dasd_profile_exit(struct dasd_profile *profile)
+{
+       return;
+}
+
+int dasd_profile_on(struct dasd_profile *profile)
+{
+       return 0;
+}
+
 #endif                         /* CONFIG_DASD_PROFILE */
 
 /*
@@ -2441,6 +2924,7 @@ dasd_exit(void)
                debug_unregister(dasd_debug_area);
                dasd_debug_area = NULL;
        }
+       dasd_statistics_removeroot();
 }
 
 /*
@@ -2992,6 +3476,8 @@ static int __init dasd_init(void)
 
        dasd_diag_discipline_pointer = NULL;
 
+       dasd_statistics_createroot();
+
        rc = dasd_devmap_init();
        if (rc)
                goto failed;
index d1e4f2c..1dd12bd 100644 (file)
@@ -382,6 +382,41 @@ struct dasd_path {
        __u8 npm;
 };
 
+struct dasd_profile_info {
+       /* legacy part of profile data, as in dasd_profile_info_t */
+       unsigned int dasd_io_reqs;       /* number of requests processed */
+       unsigned int dasd_io_sects;      /* number of sectors processed */
+       unsigned int dasd_io_secs[32];   /* histogram of request's sizes */
+       unsigned int dasd_io_times[32];  /* histogram of requests's times */
+       unsigned int dasd_io_timps[32];  /* h. of requests's times per sector */
+       unsigned int dasd_io_time1[32];  /* hist. of time from build to start */
+       unsigned int dasd_io_time2[32];  /* hist. of time from start to irq */
+       unsigned int dasd_io_time2ps[32]; /* hist. of time from start to irq */
+       unsigned int dasd_io_time3[32];  /* hist. of time from irq to end */
+       unsigned int dasd_io_nr_req[32]; /* hist. of # of requests in chanq */
+
+       /* new data */
+       struct timespec starttod;          /* time of start or last reset */
+       unsigned int dasd_io_alias;        /* requests using an alias */
+       unsigned int dasd_io_tpm;          /* requests using transport mode */
+       unsigned int dasd_read_reqs;       /* total number of read  requests */
+       unsigned int dasd_read_sects;      /* total number read sectors */
+       unsigned int dasd_read_alias;      /* read request using an alias */
+       unsigned int dasd_read_tpm;        /* read requests in transport mode */
+       unsigned int dasd_read_secs[32];   /* histogram of request's sizes */
+       unsigned int dasd_read_times[32];  /* histogram of requests's times */
+       unsigned int dasd_read_time1[32];  /* hist. time from build to start */
+       unsigned int dasd_read_time2[32];  /* hist. of time from start to irq */
+       unsigned int dasd_read_time3[32];  /* hist. of time from irq to end */
+       unsigned int dasd_read_nr_req[32]; /* hist. of # of requests in chanq */
+};
+
+struct dasd_profile {
+       struct dentry *dentry;
+       struct dasd_profile_info *data;
+       spinlock_t lock;
+};
+
 struct dasd_device {
        /* Block device stuff. */
        struct dasd_block *block;
@@ -431,6 +466,9 @@ struct dasd_device {
 
        /* default expiration time in s */
        unsigned long default_expires;
+
+       struct dentry *debugfs_dentry;
+       struct dasd_profile profile;
 };
 
 struct dasd_block {
@@ -453,9 +491,8 @@ struct dasd_block {
        struct tasklet_struct tasklet;
        struct timer_list timer;
 
-#ifdef CONFIG_DASD_PROFILE
-       struct dasd_profile_info_t profile;
-#endif
+       struct dentry *debugfs_dentry;
+       struct dasd_profile profile;
 };
 
 
@@ -589,12 +626,13 @@ dasd_check_blocksize(int bsize)
 }
 
 /* externals in dasd.c */
-#define DASD_PROFILE_ON         1
-#define DASD_PROFILE_OFF 0
+#define DASD_PROFILE_OFF        0
+#define DASD_PROFILE_ON         1
+#define DASD_PROFILE_GLOBAL_ONLY 2
 
 extern debug_info_t *dasd_debug_area;
-extern struct dasd_profile_info_t dasd_global_profile;
-extern unsigned int dasd_profile_level;
+extern struct dasd_profile_info dasd_global_profile_data;
+extern unsigned int dasd_global_profile_level;
 extern const struct block_device_operations dasd_device_operations;
 
 extern struct kmem_cache *dasd_page_cache;
@@ -662,6 +700,11 @@ void dasd_device_remove_stop_bits(struct dasd_device *, int);
 
 int dasd_device_is_ro(struct dasd_device *);
 
+void dasd_profile_reset(struct dasd_profile *);
+int dasd_profile_on(struct dasd_profile *);
+void dasd_profile_off(struct dasd_profile *);
+void dasd_global_profile_reset(void);
+char *dasd_get_user_string(const char __user *, size_t);
 
 /* externals in dasd_devmap.c */
 extern int dasd_max_devindex;
index 72261e4..eb4e034 100644 (file)
@@ -239,7 +239,7 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
  */
 static int dasd_ioctl_reset_profile(struct dasd_block *block)
 {
-       memset(&block->profile, 0, sizeof(struct dasd_profile_info_t));
+       dasd_profile_reset(&block->profile);
        return 0;
 }
 
@@ -248,10 +248,40 @@ static int dasd_ioctl_reset_profile(struct dasd_block *block)
  */
 static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
 {
-       if (dasd_profile_level == DASD_PROFILE_OFF)
+       struct dasd_profile_info_t *data;
+
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock_bh(&block->profile.lock);
+       if (block->profile.data) {
+               data->dasd_io_reqs = block->profile.data->dasd_io_reqs;
+               data->dasd_io_sects = block->profile.data->dasd_io_sects;
+               memcpy(data->dasd_io_secs, block->profile.data->dasd_io_secs,
+                      sizeof(data->dasd_io_secs));
+               memcpy(data->dasd_io_times, block->profile.data->dasd_io_times,
+                      sizeof(data->dasd_io_times));
+               memcpy(data->dasd_io_timps, block->profile.data->dasd_io_timps,
+                      sizeof(data->dasd_io_timps));
+               memcpy(data->dasd_io_time1, block->profile.data->dasd_io_time1,
+                      sizeof(data->dasd_io_time1));
+               memcpy(data->dasd_io_time2, block->profile.data->dasd_io_time2,
+                      sizeof(data->dasd_io_time2));
+               memcpy(data->dasd_io_time2ps,
+                      block->profile.data->dasd_io_time2ps,
+                      sizeof(data->dasd_io_time2ps));
+               memcpy(data->dasd_io_time3, block->profile.data->dasd_io_time3,
+                      sizeof(data->dasd_io_time3));
+               memcpy(data->dasd_io_nr_req,
+                      block->profile.data->dasd_io_nr_req,
+                      sizeof(data->dasd_io_nr_req));
+               spin_unlock_bh(&block->profile.lock);
+       } else {
+               spin_unlock_bh(&block->profile.lock);
                return -EIO;
-       if (copy_to_user(argp, &block->profile,
-                        sizeof(struct dasd_profile_info_t)))
+       }
+       if (copy_to_user(argp, data, sizeof(*data)))
                return -EFAULT;
        return 0;
 }
index c4a6a31..6c3c536 100644 (file)
@@ -32,28 +32,6 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
 static struct proc_dir_entry *dasd_devices_entry = NULL;
 static struct proc_dir_entry *dasd_statistics_entry = NULL;
 
-#ifdef CONFIG_DASD_PROFILE
-static char *
-dasd_get_user_string(const char __user *user_buf, size_t user_len)
-{
-       char *buffer;
-
-       buffer = kmalloc(user_len + 1, GFP_KERNEL);
-       if (buffer == NULL)
-               return ERR_PTR(-ENOMEM);
-       if (copy_from_user(buffer, user_buf, user_len) != 0) {
-               kfree(buffer);
-               return ERR_PTR(-EFAULT);
-       }
-       /* got the string, now strip linefeed. */
-       if (buffer[user_len - 1] == '\n')
-               buffer[user_len - 1] = 0;
-       else
-               buffer[user_len] = 0;
-       return buffer;
-}
-#endif /* CONFIG_DASD_PROFILE */
-
 static int
 dasd_devices_show(struct seq_file *m, void *v)
 {
@@ -167,6 +145,55 @@ static const struct file_operations dasd_devices_file_ops = {
 };
 
 #ifdef CONFIG_DASD_PROFILE
+static int dasd_stats_all_block_on(void)
+{
+       int i, rc;
+       struct dasd_device *device;
+
+       rc = 0;
+       for (i = 0; i < dasd_max_devindex; ++i) {
+               device = dasd_device_from_devindex(i);
+               if (IS_ERR(device))
+                       continue;
+               if (device->block)
+                       rc = dasd_profile_on(&device->block->profile);
+               dasd_put_device(device);
+               if (rc)
+                       return rc;
+       }
+       return 0;
+}
+
+static void dasd_stats_all_block_off(void)
+{
+       int i;
+       struct dasd_device *device;
+
+       for (i = 0; i < dasd_max_devindex; ++i) {
+               device = dasd_device_from_devindex(i);
+               if (IS_ERR(device))
+                       continue;
+               if (device->block)
+                       dasd_profile_off(&device->block->profile);
+               dasd_put_device(device);
+       }
+}
+
+static void dasd_stats_all_block_reset(void)
+{
+       int i;
+       struct dasd_device *device;
+
+       for (i = 0; i < dasd_max_devindex; ++i) {
+               device = dasd_device_from_devindex(i);
+               if (IS_ERR(device))
+                       continue;
+               if (device->block)
+                       dasd_profile_reset(&device->block->profile);
+               dasd_put_device(device);
+       }
+}
+
 static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int factor)
 {
        int i;
@@ -183,18 +210,18 @@ static void dasd_statistics_array(struct seq_file *m, unsigned int *array, int f
 static int dasd_stats_proc_show(struct seq_file *m, void *v)
 {
 #ifdef CONFIG_DASD_PROFILE
-       struct dasd_profile_info_t *prof;
+       struct dasd_profile_info *prof;
        int factor;
 
        /* check for active profiling */
-       if (dasd_profile_level == DASD_PROFILE_OFF) {
+       if (!dasd_global_profile_level) {
                seq_printf(m, "Statistics are off - they might be "
                                    "switched on using 'echo set on > "
                                    "/proc/dasd/statistics'\n");
                return 0;
        }
+       prof = &dasd_global_profile_data;
 
-       prof = &dasd_global_profile;
        /* prevent counter 'overflow' on output */
        for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999;
             factor *= 10);
@@ -245,6 +272,7 @@ static ssize_t dasd_stats_proc_write(struct file *file,
 {
 #ifdef CONFIG_DASD_PROFILE
        char *buffer, *str;
+       int rc;
 
        if (user_len > 65536)
                user_len = 65536;
@@ -259,32 +287,40 @@ static ssize_t dasd_stats_proc_write(struct file *file,
                str = skip_spaces(str + 4);
                if (strcmp(str, "on") == 0) {
                        /* switch on statistics profiling */
-                       dasd_profile_level = DASD_PROFILE_ON;
+                       rc = dasd_stats_all_block_on();
+                       if (rc) {
+                               dasd_stats_all_block_off();
+                               goto out_error;
+                       }
+                       dasd_global_profile_reset();
+                       dasd_global_profile_level = DASD_PROFILE_ON;
                        pr_info("The statistics feature has been switched "
                                "on\n");
                } else if (strcmp(str, "off") == 0) {
                        /* switch off and reset statistics profiling */
-                       memset(&dasd_global_profile,
-                              0, sizeof (struct dasd_profile_info_t));
-                       dasd_profile_level = DASD_PROFILE_OFF;
+                       dasd_global_profile_level = DASD_PROFILE_OFF;
+                       dasd_global_profile_reset();
+                       dasd_stats_all_block_off();
                        pr_info("The statistics feature has been switched "
                                "off\n");
                } else
-                       goto out_error;
+                       goto out_parse_error;
        } else if (strncmp(str, "reset", 5) == 0) {
                /* reset the statistics */
-               memset(&dasd_global_profile, 0,
-                      sizeof (struct dasd_profile_info_t));
+               dasd_global_profile_reset();
+               dasd_stats_all_block_reset();
                pr_info("The statistics have been reset\n");
        } else
-               goto out_error;
+               goto out_parse_error;
        kfree(buffer);
        return user_len;
-out_error:
+out_parse_error:
+       rc = -EINVAL;
        pr_warning("%s is not a supported value for /proc/dasd/statistics\n",
                str);
+out_error:
        kfree(buffer);
-       return -EINVAL;
+       return rc;
 #else
        pr_warning("/proc/dasd/statistics: is not activated in this kernel\n");
        return user_len;
index a4f117d..2c9a776 100644 (file)
@@ -116,9 +116,6 @@ config S390_TAPE
          called tape390 and include all selected interfaces and
          hardware drivers.
 
-comment "S/390 tape interface support"
-       depends on S390_TAPE
-
 comment "S/390 tape hardware support"
        depends on S390_TAPE
 
index 5c4e741..68be6e1 100644 (file)
@@ -95,9 +95,11 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr)
        }
 }
 
-static inline u32 shared_ind_set(void)
+static inline u32 clear_shared_ind(void)
 {
-       return q_indicators[TIQDIO_SHARED_IND].ind;
+       if (!atomic_read(&q_indicators[TIQDIO_SHARED_IND].count))
+               return 0;
+       return xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
 }
 
 /**
@@ -107,7 +109,7 @@ static inline u32 shared_ind_set(void)
  */
 static void tiqdio_thinint_handler(void *alsi, void *data)
 {
-       u32 si_used = shared_ind_set();
+       u32 si_used = clear_shared_ind();
        struct qdio_q *q;
 
        last_ai_time = S390_lowcore.int_clock;
@@ -150,13 +152,6 @@ static void tiqdio_thinint_handler(void *alsi, void *data)
                qperf_inc(q, adapter_int);
        }
        rcu_read_unlock();
-
-       /*
-        * If the shared indicator was used clear it now after all queues
-        * were processed.
-        */
-       if (si_used && shared_ind_set())
-               xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 0);
 }
 
 static int set_subchannel_ind(struct qdio_irq *irq_ptr, int reset)
index 16e4a25..f8134a4 100644 (file)
@@ -6,6 +6,7 @@
  *           Martin Schwidefsky <schwidefsky@de.ibm.com>
  *           Ralph Wuerthner <rwuerthn@de.ibm.com>
  *           Felix Beck <felix.beck@de.ibm.com>
+ *           Holger Dengler <hd@linux.vnet.ibm.com>
  *
  * Adjunct processor bus.
  *
@@ -222,47 +223,52 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
 }
 #endif
 
-static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid,
-                                                                 int *support)
+#ifdef CONFIG_64BIT
+static inline struct ap_queue_status
+__ap_query_functions(ap_qid_t qid, unsigned int *functions)
 {
        register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
-       register struct ap_queue_status reg1 asm ("1");
-       register unsigned long reg2 asm ("2") = 0UL;
+       register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
+       register unsigned long reg2 asm ("2");
 
        asm volatile(
                ".long 0xb2af0000\n"
-               "0: la    %1,0\n"
-               "1:\n"
-               EX_TABLE(0b, 1b)
-               : "+d" (reg0), "=d" (reg1), "=d" (reg2)
+               "0:\n"
+               EX_TABLE(0b, 0b)
+               : "+d" (reg0), "+d" (reg1), "=d" (reg2)
                :
                : "cc");
 
-       if (reg2 & 0x6000000000000000ULL)
-               *support = 1;
-       else
-               *support = 0;
-
+       *functions = (unsigned int)(reg2 >> 32);
        return reg1;
 }
+#endif
 
 /**
- * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
- * support.
+ * ap_query_functions(): Query supported functions.
  * @qid: The AP queue number
+ * @functions: Pointer to functions field.
  *
- * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ * Returns
+ *   0      on success.
+ *   -ENODEV  if queue not valid.
+ *   -EBUSY   if device busy.
+ *   -EINVAL  if query function is not supported
  */
-int ap_4096_commands_available(ap_qid_t qid)
+static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
 {
+#ifdef CONFIG_64BIT
        struct ap_queue_status status;
-       int i, support = 0;
-       status = __ap_4096_commands_available(qid, &support);
+       int i;
+       status = __ap_query_functions(qid, functions);
 
        for (i = 0; i < AP_MAX_RESET; i++) {
+               if (ap_queue_status_invalid_test(&status))
+                       return -ENODEV;
+
                switch (status.response_code) {
                case AP_RESPONSE_NORMAL:
-                       return support;
+                       return 0;
                case AP_RESPONSE_RESET_IN_PROGRESS:
                case AP_RESPONSE_BUSY:
                        break;
@@ -270,7 +276,7 @@ int ap_4096_commands_available(ap_qid_t qid)
                case AP_RESPONSE_DECONFIGURED:
                case AP_RESPONSE_CHECKSTOPPED:
                case AP_RESPONSE_INVALID_ADDRESS:
-                       return 0;
+                       return -ENODEV;
                case AP_RESPONSE_OTHERWISE_CHANGED:
                        break;
                default:
@@ -278,10 +284,31 @@ int ap_4096_commands_available(ap_qid_t qid)
                }
                if (i < AP_MAX_RESET - 1) {
                        udelay(5);
-                       status = __ap_4096_commands_available(qid, &support);
+                       status = __ap_query_functions(qid, functions);
                }
        }
-       return support;
+       return -EBUSY;
+#else
+       return -EINVAL;
+#endif
+}
+
+/**
+ * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
+ * support.
+ * @qid: The AP queue number
+ *
+ * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
+ */
+int ap_4096_commands_available(ap_qid_t qid)
+{
+       unsigned int functions;
+
+       if (ap_query_functions(qid, &functions))
+               return 0;
+
+       return test_ap_facility(functions, 1) &&
+              test_ap_facility(functions, 2);
 }
 EXPORT_SYMBOL(ap_4096_commands_available);
 
@@ -1135,6 +1162,7 @@ static void ap_scan_bus(struct work_struct *unused)
        struct device *dev;
        ap_qid_t qid;
        int queue_depth, device_type;
+       unsigned int device_functions;
        int rc, i;
 
        if (ap_select_domain() != 0)
@@ -1183,14 +1211,30 @@ static void ap_scan_bus(struct work_struct *unused)
                INIT_LIST_HEAD(&ap_dev->list);
                setup_timer(&ap_dev->timeout, ap_request_timeout,
                            (unsigned long) ap_dev);
-               if (device_type == 0) {
+               switch (device_type) {
+               case 0:
                        if (ap_probe_device_type(ap_dev)) {
                                kfree(ap_dev);
                                continue;
                        }
-               }
-               else
+                       break;
+               case 10:
+                       if (ap_query_functions(qid, &device_functions)) {
+                               kfree(ap_dev);
+                               continue;
+                       }
+                       if (test_ap_facility(device_functions, 3))
+                               ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
+                       else if (test_ap_facility(device_functions, 4))
+                               ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
+                       else {
+                               kfree(ap_dev);
+                               continue;
+                       }
+                       break;
+               default:
                        ap_dev->device_type = device_type;
+               }
 
                ap_dev->device.bus = &ap_bus_type;
                ap_dev->device.parent = ap_root_device;
index 08b9738..d960a63 100644 (file)
@@ -6,6 +6,7 @@
  *           Martin Schwidefsky <schwidefsky@de.ibm.com>
  *           Ralph Wuerthner <rwuerthn@de.ibm.com>
  *           Felix Beck <felix.beck@de.ibm.com>
+ *           Holger Dengler <hd@linux.vnet.ibm.com>
  *
  * Adjunct processor bus header file.
  *
@@ -72,7 +73,26 @@ struct ap_queue_status {
        unsigned int int_enabled        : 1;
        unsigned int response_code      : 8;
        unsigned int pad2               : 16;
-};
+} __packed;
+
+#define AP_QUEUE_STATUS_INVALID \
+               { 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
+
+static inline
+int ap_queue_status_invalid_test(struct ap_queue_status *status)
+{
+       struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
+       return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
+}
+
+#define MAX_AP_FACILITY 31
+
+static inline int test_ap_facility(unsigned int function, unsigned int nr)
+{
+       if (nr > MAX_AP_FACILITY)
+               return 0;
+       return function & (unsigned int)(0x80000000 >> nr);
+}
 
 #define AP_RESPONSE_NORMAL             0x00
 #define AP_RESPONSE_Q_NOT_AVAIL                0x01
index 2540a39..9701574 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -869,11 +869,11 @@ int page_referenced(struct page *page,
                                                                vm_flags);
                if (we_locked)
                        unlock_page(page);
+
+               if (page_test_and_clear_young(page_to_pfn(page)))
+                       referenced++;
        }
 out:
-       if (page_test_and_clear_young(page_to_pfn(page)))
-               referenced++;
-
        return referenced;
 }
 
index 7f91249..f2b7138 100644 (file)
@@ -1988,12 +1988,13 @@ static int __init iucv_init(void)
                rc = -EPROTONOSUPPORT;
                goto out;
        }
+       ctl_set_bit(0, 1);
        rc = iucv_query_maxconn();
        if (rc)
-               goto out;
+               goto out_ctl;
        rc = register_external_interrupt(0x4000, iucv_external_interrupt);
        if (rc)
-               goto out;
+               goto out_ctl;
        iucv_root = root_device_register("iucv");
        if (IS_ERR(iucv_root)) {
                rc = PTR_ERR(iucv_root);
@@ -2055,6 +2056,8 @@ out_free:
        root_device_unregister(iucv_root);
 out_int:
        unregister_external_interrupt(0x4000, iucv_external_interrupt);
+out_ctl:
+       ctl_clear_bit(0, 1);
 out:
        return rc;
 }