aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/cpcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/cpcmd.c')
-rw-r--r--arch/s390/kernel/cpcmd.c83
1 files changed, 30 insertions, 53 deletions
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 4ef44e536b2c..1eae74e72f95 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -25,11 +25,8 @@ static char cpcmd_buf[241];
25 */ 25 */
26int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) 26int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
27{ 27{
28 const int mask = 0x40000000L; 28 unsigned long flags, cmdlen;
29 unsigned long flags; 29 int return_code, return_len;
30 int return_code;
31 int return_len;
32 int cmdlen;
33 30
34 spin_lock_irqsave(&cpcmd_lock, flags); 31 spin_lock_irqsave(&cpcmd_lock, flags);
35 cmdlen = strlen(cmd); 32 cmdlen = strlen(cmd);
@@ -38,64 +35,44 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
38 ASCEBC(cpcmd_buf, cmdlen); 35 ASCEBC(cpcmd_buf, cmdlen);
39 36
40 if (response != NULL && rlen > 0) { 37 if (response != NULL && rlen > 0) {
38 register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
39 register unsigned long reg3 asm ("3") = (addr_t) response;
40 register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
41 register unsigned long reg5 asm ("5") = rlen;
42
41 memset(response, 0, rlen); 43 memset(response, 0, rlen);
44 asm volatile(
42#ifndef CONFIG_64BIT 45#ifndef CONFIG_64BIT
43 asm volatile ( "lra 2,0(%2)\n" 46 " diag %2,%0,0x8\n"
44 "lr 4,%3\n" 47 " brc 8,1f\n"
45 "o 4,%6\n" 48 " ar %1,%4\n"
46 "lra 3,0(%4)\n"
47 "lr 5,%5\n"
48 "diag 2,4,0x8\n"
49 "brc 8, 1f\n"
50 "ar 5, %5\n"
51 "1: \n"
52 "lr %0,4\n"
53 "lr %1,5\n"
54 : "=d" (return_code), "=d" (return_len)
55 : "a" (cpcmd_buf), "d" (cmdlen),
56 "a" (response), "d" (rlen), "m" (mask)
57 : "cc", "2", "3", "4", "5" );
58#else /* CONFIG_64BIT */ 49#else /* CONFIG_64BIT */
59 asm volatile ( "lrag 2,0(%2)\n" 50 " sam31\n"
60 "lgr 4,%3\n" 51 " diag %2,%0,0x8\n"
61 "o 4,%6\n" 52 " sam64\n"
62 "lrag 3,0(%4)\n" 53 " brc 8,1f\n"
63 "lgr 5,%5\n" 54 " agr %1,%4\n"
64 "sam31\n"
65 "diag 2,4,0x8\n"
66 "sam64\n"
67 "brc 8, 1f\n"
68 "agr 5, %5\n"
69 "1: \n"
70 "lgr %0,4\n"
71 "lgr %1,5\n"
72 : "=d" (return_code), "=d" (return_len)
73 : "a" (cpcmd_buf), "d" (cmdlen),
74 "a" (response), "d" (rlen), "m" (mask)
75 : "cc", "2", "3", "4", "5" );
76#endif /* CONFIG_64BIT */ 55#endif /* CONFIG_64BIT */
56 "1:\n"
57 : "+d" (reg4), "+d" (reg5)
58 : "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
59 return_code = (int) reg4;
60 return_len = (int) reg5;
77 EBCASC(response, rlen); 61 EBCASC(response, rlen);
78 } else { 62 } else {
63 register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
64 register unsigned long reg3 asm ("3") = cmdlen;
79 return_len = 0; 65 return_len = 0;
66 asm volatile(
80#ifndef CONFIG_64BIT 67#ifndef CONFIG_64BIT
81 asm volatile ( "lra 2,0(%1)\n" 68 " diag %1,%0,0x8\n"
82 "lr 3,%2\n"
83 "diag 2,3,0x8\n"
84 "lr %0,3\n"
85 : "=d" (return_code)
86 : "a" (cpcmd_buf), "d" (cmdlen)
87 : "2", "3" );
88#else /* CONFIG_64BIT */ 69#else /* CONFIG_64BIT */
89 asm volatile ( "lrag 2,0(%1)\n" 70 " sam31\n"
90 "lgr 3,%2\n" 71 " diag %1,%0,0x8\n"
91 "sam31\n" 72 " sam64\n"
92 "diag 2,3,0x8\n"
93 "sam64\n"
94 "lgr %0,3\n"
95 : "=d" (return_code)
96 : "a" (cpcmd_buf), "d" (cmdlen)
97 : "2", "3" );
98#endif /* CONFIG_64BIT */ 73#endif /* CONFIG_64BIT */
74 : "+d" (reg3) : "d" (reg2) : "cc");
75 return_code = (int) reg3;
99 } 76 }
100 spin_unlock_irqrestore(&cpcmd_lock, flags); 77 spin_unlock_irqrestore(&cpcmd_lock, flags);
101 if (response_code != NULL) 78 if (response_code != NULL)