aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-10-12 10:11:46 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-10-12 10:13:09 -0400
commita004fb0c33539ae90f25573505be6a116a76e639 (patch)
tree791e4b5904ab1b5273dce3c4625664a411388464 /arch
parente39394b84156bc0822785e379977fe75a5662aad (diff)
[S390] cpcmd: fix inline assembly usage.
After assigning values to specific registers memset was called. This may clobber the contents of the used registers. To solve this extract the two used inline assemblies into small functions that don't call any functions. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/kernel/cpcmd.c100
1 files changed, 55 insertions, 45 deletions
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 6c89f30c8e31..d8c1131e0815 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -2,7 +2,7 @@
2 * arch/s390/kernel/cpcmd.c 2 * arch/s390/kernel/cpcmd.c
3 * 3 *
4 * S390 version 4 * S390 version
5 * Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation 5 * Copyright IBM Corp. 1999,2007
6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7 * Christian Borntraeger (cborntra@de.ibm.com), 7 * Christian Borntraeger (cborntra@de.ibm.com),
8 */ 8 */
@@ -21,6 +21,49 @@
21static DEFINE_SPINLOCK(cpcmd_lock); 21static DEFINE_SPINLOCK(cpcmd_lock);
22static char cpcmd_buf[241]; 22static char cpcmd_buf[241];
23 23
24static int diag8_noresponse(int cmdlen)
25{
26 register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
27 register unsigned long reg3 asm ("3") = cmdlen;
28
29 asm volatile(
30#ifndef CONFIG_64BIT
31 " diag %1,%0,0x8\n"
32#else /* CONFIG_64BIT */
33 " sam31\n"
34 " diag %1,%0,0x8\n"
35 " sam64\n"
36#endif /* CONFIG_64BIT */
37 : "+d" (reg3) : "d" (reg2) : "cc");
38 return reg3;
39}
40
41static int diag8_response(int cmdlen, char *response, int *rlen)
42{
43 register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
44 register unsigned long reg3 asm ("3") = (addr_t) response;
45 register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
46 register unsigned long reg5 asm ("5") = *rlen;
47
48 asm volatile(
49#ifndef CONFIG_64BIT
50 " diag %2,%0,0x8\n"
51 " brc 8,1f\n"
52 " ar %1,%4\n"
53#else /* CONFIG_64BIT */
54 " sam31\n"
55 " diag %2,%0,0x8\n"
56 " sam64\n"
57 " brc 8,1f\n"
58 " agr %1,%4\n"
59#endif /* CONFIG_64BIT */
60 "1:\n"
61 : "+d" (reg4), "+d" (reg5)
62 : "d" (reg2), "d" (reg3), "d" (*rlen) : "cc");
63 *rlen = reg5;
64 return reg4;
65}
66
24/* 67/*
25 * __cpcmd has some restrictions over cpcmd 68 * __cpcmd has some restrictions over cpcmd
26 * - the response buffer must reside below 2GB (if any) 69 * - the response buffer must reside below 2GB (if any)
@@ -28,59 +71,27 @@ static char cpcmd_buf[241];
28 */ 71 */
29int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) 72int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
30{ 73{
31 unsigned cmdlen; 74 int cmdlen;
32 int return_code, return_len; 75 int rc;
76 int response_len;
33 77
34 cmdlen = strlen(cmd); 78 cmdlen = strlen(cmd);
35 BUG_ON(cmdlen > 240); 79 BUG_ON(cmdlen > 240);
36 memcpy(cpcmd_buf, cmd, cmdlen); 80 memcpy(cpcmd_buf, cmd, cmdlen);
37 ASCEBC(cpcmd_buf, cmdlen); 81 ASCEBC(cpcmd_buf, cmdlen);
38 82
39 if (response != NULL && rlen > 0) { 83 if (response) {
40 register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
41 register unsigned long reg3 asm ("3") = (addr_t) response;
42 register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
43 register unsigned long reg5 asm ("5") = rlen;
44
45 memset(response, 0, rlen); 84 memset(response, 0, rlen);
46 asm volatile( 85 response_len = rlen;
47#ifndef CONFIG_64BIT 86 rc = diag8_response(cmdlen, response, &rlen);
48 " diag %2,%0,0x8\n" 87 EBCASC(response, response_len);
49 " brc 8,1f\n"
50 " ar %1,%4\n"
51#else /* CONFIG_64BIT */
52 " sam31\n"
53 " diag %2,%0,0x8\n"
54 " sam64\n"
55 " brc 8,1f\n"
56 " agr %1,%4\n"
57#endif /* CONFIG_64BIT */
58 "1:\n"
59 : "+d" (reg4), "+d" (reg5)
60 : "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
61 return_code = (int) reg4;
62 return_len = (int) reg5;
63 EBCASC(response, rlen);
64 } else { 88 } else {
65 register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; 89 rc = diag8_noresponse(cmdlen);
66 register unsigned long reg3 asm ("3") = cmdlen;
67 return_len = 0;
68 asm volatile(
69#ifndef CONFIG_64BIT
70 " diag %1,%0,0x8\n"
71#else /* CONFIG_64BIT */
72 " sam31\n"
73 " diag %1,%0,0x8\n"
74 " sam64\n"
75#endif /* CONFIG_64BIT */
76 : "+d" (reg3) : "d" (reg2) : "cc");
77 return_code = (int) reg3;
78 } 90 }
79 if (response_code != NULL) 91 if (response_code)
80 *response_code = return_code; 92 *response_code = rc;
81 return return_len; 93 return rlen;
82} 94}
83
84EXPORT_SYMBOL(__cpcmd); 95EXPORT_SYMBOL(__cpcmd);
85 96
86int cpcmd(const char *cmd, char *response, int rlen, int *response_code) 97int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
@@ -109,5 +120,4 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
109 } 120 }
110 return len; 121 return len;
111} 122}
112
113EXPORT_SYMBOL(cpcmd); 123EXPORT_SYMBOL(cpcmd);