summaryrefslogtreecommitdiff
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];
*/
int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
- const int mask = 0x40000000L;
- unsigned long flags;
- int return_code;
- int return_len;
- int cmdlen;
+ unsigned long flags, cmdlen;
+ int return_code, return_len;
spin_lock_irqsave(&cpcmd_lock, flags);
cmdlen = strlen(cmd);
@@ -38,64 +35,44 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
ASCEBC(cpcmd_buf, cmdlen);
if (response != NULL && rlen > 0) {
+ register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+ register unsigned long reg3 asm ("3") = (addr_t) response;
+ register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
+ register unsigned long reg5 asm ("5") = rlen;
+
memset(response, 0, rlen);
+ asm volatile(
#ifndef CONFIG_64BIT
- asm volatile ( "lra 2,0(%2)\n"
- "lr 4,%3\n"
- "o 4,%6\n"
- "lra 3,0(%4)\n"
- "lr 5,%5\n"
- "diag 2,4,0x8\n"
- "brc 8, 1f\n"
- "ar 5, %5\n"
- "1: \n"
- "lr %0,4\n"
- "lr %1,5\n"
- : "=d" (return_code), "=d" (return_len)
- : "a" (cpcmd_buf), "d" (cmdlen),
- "a" (response), "d" (rlen), "m" (mask)
- : "cc", "2", "3", "4", "5" );
+ " diag %2,%0,0x8\n"
+ " brc 8,1f\n"
+ " ar %1,%4\n"
#else /* CONFIG_64BIT */
- asm volatile ( "lrag 2,0(%2)\n"
- "lgr 4,%3\n"
- "o 4,%6\n"
- "lrag 3,0(%4)\n"
- "lgr 5,%5\n"
- "sam31\n"
- "diag 2,4,0x8\n"
- "sam64\n"
- "brc 8, 1f\n"
- "agr 5, %5\n"
- "1: \n"
- "lgr %0,4\n"
- "lgr %1,5\n"
- : "=d" (return_code), "=d" (return_len)
- : "a" (cpcmd_buf), "d" (cmdlen),
- "a" (response), "d" (rlen), "m" (mask)
- : "cc", "2", "3", "4", "5" );
+ " sam31\n"
+ " diag %2,%0,0x8\n"
+ " sam64\n"
+ " brc 8,1f\n"
+ " agr %1,%4\n"
#endif /* CONFIG_64BIT */
+ "1:\n"
+ : "+d" (reg4), "+d" (reg5)
+ : "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
+ return_code = (int) reg4;
+ return_len = (int) reg5;
EBCASC(response, rlen);
} else {
+ register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+ register unsigned long reg3 asm ("3") = cmdlen;
return_len = 0;
+ asm volatile(
#ifndef CONFIG_64BIT
- asm volatile ( "lra 2,0(%1)\n"
- "lr 3,%2\n"
- "diag 2,3,0x8\n"
- "lr %0,3\n"
- : "=d" (return_code)
- : "a" (cpcmd_buf), "d" (cmdlen)
- : "2", "3" );
+ " diag %1,%0,0x8\n"
#else /* CONFIG_64BIT */
- asm volatile ( "lrag 2,0(%1)\n"
- "lgr 3,%2\n"
- "sam31\n"
- "diag 2,3,0x8\n"
- "sam64\n"
- "lgr %0,3\n"
- : "=d" (return_code)
- : "a" (cpcmd_buf), "d" (cmdlen)
- : "2", "3" );
+ " sam31\n"
+ " diag %1,%0,0x8\n"
+ " sam64\n"
#endif /* CONFIG_64BIT */
+ : "+d" (reg3) : "d" (reg2) : "cc");
+ return_code = (int) reg3;
}
spin_unlock_irqrestore(&cpcmd_lock, flags);
if (response_code != NULL)