1 /*
2 * Implementation of s390 diagnose codes
3 *
4 * Copyright IBM Corp. 2007
5 * Author(s): Michael Holzheu <holzheu@de.ibm.com>
6 */
7
8 #include <linux/module.h>
9 #include <asm/diag.h>
10
11 /*
12 * Diagnose 10: Release pages
13 */
diag10(unsigned long addr)14 void diag10(unsigned long addr)
15 {
16 if (addr >= 0x7ff00000)
17 return;
18 asm volatile(
19 #ifdef CONFIG_64BIT
20 " sam31\n"
21 " diag %0,%0,0x10\n"
22 "0: sam64\n"
23 #else
24 " diag %0,%0,0x10\n"
25 "0:\n"
26 #endif
27 EX_TABLE(0b, 0b)
28 : : "a" (addr));
29 }
30 EXPORT_SYMBOL(diag10);
31
32 /*
33 * Diagnose 14: Input spool file manipulation
34 */
diag14(unsigned long rx,unsigned long ry1,unsigned long subcode)35 int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
36 {
37 register unsigned long _ry1 asm("2") = ry1;
38 register unsigned long _ry2 asm("3") = subcode;
39 int rc = 0;
40
41 asm volatile(
42 #ifdef CONFIG_64BIT
43 " sam31\n"
44 " diag %2,2,0x14\n"
45 " sam64\n"
46 #else
47 " diag %2,2,0x14\n"
48 #endif
49 " ipm %0\n"
50 " srl %0,28\n"
51 : "=d" (rc), "+d" (_ry2)
52 : "d" (rx), "d" (_ry1)
53 : "cc");
54
55 return rc;
56 }
57 EXPORT_SYMBOL(diag14);
58
59 /*
60 * Diagnose 210: Get information about a virtual device
61 */
diag210(struct diag210 * addr)62 int diag210(struct diag210 *addr)
63 {
64 /*
65 * diag 210 needs its data below the 2GB border, so we
66 * use a static data area to be sure
67 */
68 static struct diag210 diag210_tmp;
69 static DEFINE_SPINLOCK(diag210_lock);
70 unsigned long flags;
71 int ccode;
72
73 spin_lock_irqsave(&diag210_lock, flags);
74 diag210_tmp = *addr;
75
76 #ifdef CONFIG_64BIT
77 asm volatile(
78 " lhi %0,-1\n"
79 " sam31\n"
80 " diag %1,0,0x210\n"
81 "0: ipm %0\n"
82 " srl %0,28\n"
83 "1: sam64\n"
84 EX_TABLE(0b, 1b)
85 : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
86 #else
87 asm volatile(
88 " lhi %0,-1\n"
89 " diag %1,0,0x210\n"
90 "0: ipm %0\n"
91 " srl %0,28\n"
92 "1:\n"
93 EX_TABLE(0b, 1b)
94 : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
95 #endif
96
97 *addr = diag210_tmp;
98 spin_unlock_irqrestore(&diag210_lock, flags);
99
100 return ccode;
101 }
102 EXPORT_SYMBOL(diag210);
103