summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2006-07-19 08:01:28 +1000
committerPaul Mackerras <paulus@samba.org>2006-08-01 16:19:15 +1000
commitb9377ffc3a03cde558d76349a262a1adbb6d3112 (patch)
treec61fcdb732d06c64b9c5634953e46cefdf6af846 /arch/powerpc
parent57cad8084e0837e0f2c97da789ec9b3f36809be9 (diff)
downloadop-kernel-dev-b9377ffc3a03cde558d76349a262a1adbb6d3112.zip
op-kernel-dev-b9377ffc3a03cde558d76349a262a1adbb6d3112.tar.gz
[POWERPC] clean up pseries hcall interfaces
Our pseries hcall interfaces are out of control: plpar_hcall_norets plpar_hcall plpar_hcall_8arg_2ret plpar_hcall_4out plpar_hcall_7arg_7ret plpar_hcall_9arg_9ret Create 3 interfaces to cover all cases: plpar_hcall_norets: 7 arguments no returns plpar_hcall: 6 arguments 4 returns plpar_hcall9: 9 arguments 9 returns There are only 2 cases in the kernel that need plpar_hcall9, hopefully we can keep it that way. Pass in a buffer to stash return parameters so we avoid the &dummy1, &dummy2 madness. Signed-off-by: Anton Blanchard <anton@samba.org> -- Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/lparcfg.c18
-rw-r--r--arch/powerpc/kernel/rtas.c11
-rw-r--r--arch/powerpc/platforms/pseries/hvCall.S207
-rw-r--r--arch/powerpc/platforms/pseries/hvconsole.c5
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c12
-rw-r--r--arch/powerpc/platforms/pseries/plpar_wrappers.h97
-rw-r--r--arch/powerpc/platforms/pseries/xics.c22
7 files changed, 142 insertions, 230 deletions
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 3ce3a2d..41c05dc 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -182,8 +182,14 @@ static unsigned int h_get_ppp(unsigned long *entitled,
unsigned long *resource)
{
unsigned long rc;
- rc = plpar_hcall_4out(H_GET_PPP, 0, 0, 0, 0, entitled, unallocated,
- aggregation, resource);
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_GET_PPP, retbuf);
+
+ *entitled = retbuf[0];
+ *unallocated = retbuf[1];
+ *aggregation = retbuf[2];
+ *resource = retbuf[3];
log_plpar_hcall_return(rc, "H_GET_PPP");
@@ -193,8 +199,12 @@ static unsigned int h_get_ppp(unsigned long *entitled,
static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
{
unsigned long rc;
- unsigned long dummy;
- rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_PIC, retbuf);
+
+ *pool_idle_time = retbuf[0];
+ *num_procs = retbuf[1];
if (rc != H_AUTHORITY)
log_plpar_hcall_return(rc, "H_PIC");
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 10e10be..14353b8 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -668,15 +668,14 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
int i;
long state;
long rc;
- unsigned long dummy;
-
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
struct rtas_suspend_me_data data;
/* Make sure the state is valid */
- rc = plpar_hcall(H_VASI_STATE,
- ((u64)args->args[0] << 32) | args->args[1],
- 0, 0, 0,
- &state, &dummy, &dummy);
+ rc = plpar_hcall(H_VASI_STATE, retbuf,
+ ((u64)args->args[0] << 32) | args->args[1]);
+
+ state = retbuf[0];
if (rc) {
printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S
index c9ff547..9a99b05 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -1,7 +1,6 @@
/*
* This file contains the generic code to perform a call to the
* pSeries LPAR hypervisor.
- * NOTE: this file will go away when we move to inline this work.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -16,42 +15,6 @@
.text
-/* long plpar_hcall(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long *out1, R8
- unsigned long *out2, R9
- unsigned long *out3); R10
- */
-_GLOBAL(plpar_hcall)
- HMT_MEDIUM
-
- mfcr r0
-
- std r8,STK_PARM(r8)(r1) /* Save out ptrs */
- std r9,STK_PARM(r9)(r1)
- std r10,STK_PARM(r10)(r1)
-
- stw r0,8(r1)
-
- HVSC /* invoke the hypervisor */
-
- lwz r0,8(r1)
-
- ld r8,STK_PARM(r8)(r1) /* Fetch r4-r6 ret args */
- ld r9,STK_PARM(r9)(r1)
- ld r10,STK_PARM(r10)(r1)
- std r4,0(r8)
- std r5,0(r9)
- std r6,0(r10)
-
- mtcrf 0xff,r0
- blr /* return r3 = status */
-
-
-/* Simple interface with no output values (other than status) */
_GLOBAL(plpar_hcall_norets)
HMT_MEDIUM
@@ -64,164 +27,64 @@ _GLOBAL(plpar_hcall_norets)
mtcrf 0xff,r0
blr /* return r3 = status */
-
-/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long arg5, R8
- unsigned long arg6, R9
- unsigned long arg7, R10
- unsigned long arg8, 112(R1)
- unsigned long *out1); 120(R1)
- */
-_GLOBAL(plpar_hcall_8arg_2ret)
+_GLOBAL(plpar_hcall)
HMT_MEDIUM
mfcr r0
- ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
stw r0,8(r1)
- HVSC /* invoke the hypervisor */
-
- lwz r0,8(r1)
- ld r10,STK_PARM(r12)(r1) /* Fetch r4 ret arg */
- std r4,0(r10)
- mtcrf 0xff,r0
- blr /* return r3 = status */
-
-
-/* long plpar_hcall_4out(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long *out1, R8
- unsigned long *out2, R9
- unsigned long *out3, R10
- unsigned long *out4); 112(R1)
- */
-_GLOBAL(plpar_hcall_4out)
- HMT_MEDIUM
-
- mfcr r0
- stw r0,8(r1)
+ std r4,STK_PARM(r4)(r1) /* Save ret buffer */
- std r8,STK_PARM(r8)(r1) /* Save out ptrs */
- std r9,STK_PARM(r9)(r1)
- std r10,STK_PARM(r10)(r1)
+ mr r4,r5
+ mr r5,r6
+ mr r6,r7
+ mr r7,r8
+ mr r8,r9
+ mr r9,r10
HVSC /* invoke the hypervisor */
- lwz r0,8(r1)
-
- ld r8,STK_PARM(r8)(r1) /* Fetch r4-r7 ret args */
- ld r9,STK_PARM(r9)(r1)
- ld r10,STK_PARM(r10)(r1)
- ld r11,STK_PARM(r11)(r1)
- std r4,0(r8)
- std r5,0(r9)
- std r6,0(r10)
- std r7,0(r11)
-
- mtcrf 0xff,r0
- blr /* return r3 = status */
-
-/* plpar_hcall_7arg_7ret(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long arg5, R8
- unsigned long arg6, R9
- unsigned long arg7, R10
- unsigned long *out1, 112(R1)
- unsigned long *out2, 110(R1)
- unsigned long *out3, 108(R1)
- unsigned long *out4, 106(R1)
- unsigned long *out5, 104(R1)
- unsigned long *out6, 102(R1)
- unsigned long *out7); 100(R1)
-*/
-_GLOBAL(plpar_hcall_7arg_7ret)
- HMT_MEDIUM
-
- mfcr r0
- stw r0,8(r1)
-
- HVSC /* invoke the hypervisor */
+ ld r12,STK_PARM(r4)(r1)
+ std r4, 0(r12)
+ std r5, 8(r12)
+ std r6, 16(r12)
+ std r7, 24(r12)
lwz r0,8(r1)
-
- ld r11,STK_PARM(r11)(r1) /* Fetch r4 ret arg */
- std r4,0(r11)
- ld r11,STK_PARM(r12)(r1) /* Fetch r5 ret arg */
- std r5,0(r11)
- ld r11,STK_PARM(r13)(r1) /* Fetch r6 ret arg */
- std r6,0(r11)
- ld r11,STK_PARM(r14)(r1) /* Fetch r7 ret arg */
- std r7,0(r11)
- ld r11,STK_PARM(r15)(r1) /* Fetch r8 ret arg */
- std r8,0(r11)
- ld r11,STK_PARM(r16)(r1) /* Fetch r9 ret arg */
- std r9,0(r11)
- ld r11,STK_PARM(r17)(r1) /* Fetch r10 ret arg */
- std r10,0(r11)
-
mtcrf 0xff,r0
blr /* return r3 = status */
-/* plpar_hcall_9arg_9ret(unsigned long opcode, R3
- unsigned long arg1, R4
- unsigned long arg2, R5
- unsigned long arg3, R6
- unsigned long arg4, R7
- unsigned long arg5, R8
- unsigned long arg6, R9
- unsigned long arg7, R10
- unsigned long arg8, 112(R1)
- unsigned long arg9, 110(R1)
- unsigned long *out1, 108(R1)
- unsigned long *out2, 106(R1)
- unsigned long *out3, 104(R1)
- unsigned long *out4, 102(R1)
- unsigned long *out5, 100(R1)
- unsigned long *out6, 98(R1)
- unsigned long *out7); 96(R1)
- unsigned long *out8, 94(R1)
- unsigned long *out9, 92(R1)
-*/
-_GLOBAL(plpar_hcall_9arg_9ret)
+_GLOBAL(plpar_hcall9)
HMT_MEDIUM
mfcr r0
stw r0,8(r1)
- ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */
- ld r12,STK_PARM(r12)(r1) /* put arg9 in R12 */
+ std r4,STK_PARM(r4)(r1) /* Save ret buffer */
+
+ mr r4,r5
+ mr r5,r6
+ mr r6,r7
+ mr r7,r8
+ mr r8,r9
+ mr r9,r10
+ ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */
+ ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */
+ ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */
HVSC /* invoke the hypervisor */
- ld r0,STK_PARM(r13)(r1) /* Fetch r4 ret arg */
- stdx r4,r0,r0
- ld r0,STK_PARM(r14)(r1) /* Fetch r5 ret arg */
- stdx r5,r0,r0
- ld r0,STK_PARM(r15)(r1) /* Fetch r6 ret arg */
- stdx r6,r0,r0
- ld r0,STK_PARM(r16)(r1) /* Fetch r7 ret arg */
- stdx r7,r0,r0
- ld r0,STK_PARM(r17)(r1) /* Fetch r8 ret arg */
- stdx r8,r0,r0
- ld r0,STK_PARM(r18)(r1) /* Fetch r9 ret arg */
- stdx r9,r0,r0
- ld r0,STK_PARM(r19)(r1) /* Fetch r10 ret arg */
- stdx r10,r0,r0
- ld r0,STK_PARM(r20)(r1) /* Fetch r11 ret arg */
- stdx r11,r0,r0
- ld r0,STK_PARM(r21)(r1) /* Fetch r12 ret arg */
- stdx r12,r0,r0
+ ld r12,STK_PARM(r4)(r1)
+ std r4, 0(r12)
+ std r5, 8(r12)
+ std r6, 16(r12)
+ std r7, 24(r12)
+ std r8, 32(r12)
+ std r9, 40(r12)
+ std r10,48(r12)
+ std r11,56(r12)
+ std r12,64(r12)
lwz r0,8(r1)
mtcrf 0xff,r0
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index a72a987..3f6a89b 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <asm/hvcall.h>
#include <asm/hvconsole.h>
+#include "plpar_wrappers.h"
/**
* hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
@@ -40,9 +41,9 @@ int hvc_get_chars(uint32_t vtermno, char *buf, int count)
{
unsigned long got;
- if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
- (unsigned long *)buf, (unsigned long *)buf+1) == H_SUCCESS)
+ if (plpar_get_term_char(vtermno, &got, buf) == H_SUCCESS)
return got;
+
return 0;
}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 4cb7ff2..6cbf142 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -48,13 +48,11 @@
#define DBG_LOW(fmt...) do { } while(0)
#endif
-/* in pSeries_hvCall.S */
+/* in hvCall.S */
EXPORT_SYMBOL(plpar_hcall);
-EXPORT_SYMBOL(plpar_hcall_4out);
+EXPORT_SYMBOL(plpar_hcall9);
EXPORT_SYMBOL(plpar_hcall_norets);
-EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
-EXPORT_SYMBOL(plpar_hcall_7arg_7ret);
-EXPORT_SYMBOL(plpar_hcall_9arg_9ret);
+
extern void pSeries_find_serial_port(void);
@@ -277,7 +275,6 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long flags;
unsigned long slot;
unsigned long hpte_v, hpte_r;
- unsigned long dummy0, dummy1;
if (!(vflags & HPTE_V_BOLTED))
DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
@@ -302,8 +299,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE))
hpte_r &= ~_PAGE_COHERENT;
- lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, hpte_v,
- hpte_r, &slot, &dummy0, &dummy1);
+ lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
if (unlikely(lpar_rc == H_PTEG_FULL)) {
if (!(vflags & HPTE_V_BOLTED))
DBG_LOW(" full\n");
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 3bd1b3e..ebd15de 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -5,20 +5,17 @@
static inline long poll_pending(void)
{
- unsigned long dummy;
- return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, &dummy, &dummy, &dummy);
+ return plpar_hcall_norets(H_POLL_PENDING);
}
static inline long prod_processor(void)
{
- plpar_hcall_norets(H_PROD);
- return 0;
+ return plpar_hcall_norets(H_PROD);
}
static inline long cede_processor(void)
{
- plpar_hcall_norets(H_CEDE);
- return 0;
+ return plpar_hcall_norets(H_CEDE);
}
static inline long vpa_call(unsigned long flags, unsigned long cpu,
@@ -42,21 +39,47 @@ static inline long register_vpa(unsigned long cpu, unsigned long vpa)
extern void vpa_init(int cpu);
+static inline long plpar_pte_enter(unsigned long flags,
+ unsigned long hpte_group, unsigned long hpte_v,
+ unsigned long hpte_r, unsigned long *slot)
+{
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_ENTER, retbuf, flags, hpte_group, hpte_v, hpte_r);
+
+ *slot = retbuf[0];
+
+ return rc;
+}
+
static inline long plpar_pte_remove(unsigned long flags, unsigned long ptex,
unsigned long avpn, unsigned long *old_pteh_ret,
unsigned long *old_ptel_ret)
{
- unsigned long dummy;
- return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0, old_pteh_ret,
- old_ptel_ret, &dummy);
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_REMOVE, retbuf, flags, ptex, avpn);
+
+ *old_pteh_ret = retbuf[0];
+ *old_ptel_ret = retbuf[1];
+
+ return rc;
}
static inline long plpar_pte_read(unsigned long flags, unsigned long ptex,
unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
{
- unsigned long dummy;
- return plpar_hcall(H_READ, flags, ptex, 0, 0, old_pteh_ret,
- old_ptel_ret, &dummy);
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_READ, retbuf, flags, ptex);
+
+ *old_pteh_ret = retbuf[0];
+ *old_ptel_ret = retbuf[1];
+
+ return rc;
}
static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
@@ -68,9 +91,14 @@ static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex,
static inline long plpar_tce_get(unsigned long liobn, unsigned long ioba,
unsigned long *tce_ret)
{
- unsigned long dummy;
- return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0, tce_ret, &dummy,
- &dummy);
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_GET_TCE, retbuf, liobn, ioba);
+
+ *tce_ret = retbuf[0];
+
+ return rc;
}
static inline long plpar_tce_put(unsigned long liobn, unsigned long ioba,
@@ -94,9 +122,17 @@ static inline long plpar_tce_stuff(unsigned long liobn, unsigned long ioba,
static inline long plpar_get_term_char(unsigned long termno,
unsigned long *len_ret, char *buf_ret)
{
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
unsigned long *lbuf = (unsigned long *)buf_ret; /* TODO: alignment? */
- return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0, len_ret,
- lbuf + 0, lbuf + 1);
+
+ rc = plpar_hcall(H_GET_TERM_CHAR, retbuf, termno);
+
+ *len_ret = retbuf[0];
+ lbuf[0] = retbuf[1];
+ lbuf[1] = retbuf[2];
+
+ return rc;
}
static inline long plpar_put_term_char(unsigned long termno, unsigned long len,
@@ -107,4 +143,31 @@ static inline long plpar_put_term_char(unsigned long termno, unsigned long len,
lbuf[1]);
}
+static inline long plpar_eoi(unsigned long xirr)
+{
+ return plpar_hcall_norets(H_EOI, xirr);
+}
+
+static inline long plpar_cppr(unsigned long cppr)
+{
+ return plpar_hcall_norets(H_CPPR, cppr);
+}
+
+static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr)
+{
+ return plpar_hcall_norets(H_IPI, servernum, mfrr);
+}
+
+static inline long plpar_xirr(unsigned long *xirr_ret)
+{
+ long rc;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ rc = plpar_hcall(H_XIRR, retbuf);
+
+ *xirr_ret = retbuf[0];
+
+ return rc;
+}
+
#endif /* _PSERIES_PLPAR_WRAPPERS_H */
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 1eab468..c88ec63 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -34,6 +34,7 @@
#include <asm/i8259.h>
#include "xics.h"
+#include "plpar_wrappers.h"
#define XICS_IPI 2
#define XICS_IRQ_SPURIOUS 0
@@ -110,27 +111,6 @@ static inline void direct_qirr_info(int n_cpu, u8 value)
/* LPAR low level accessors */
-static inline long plpar_eoi(unsigned long xirr)
-{
- return plpar_hcall_norets(H_EOI, xirr);
-}
-
-static inline long plpar_cppr(unsigned long cppr)
-{
- return plpar_hcall_norets(H_CPPR, cppr);
-}
-
-static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr)
-{
- return plpar_hcall_norets(H_IPI, servernum, mfrr);
-}
-
-static inline long plpar_xirr(unsigned long *xirr_ret)
-{
- unsigned long dummy;
- return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy);
-}
-
static inline unsigned int lpar_xirr_info_get(int n_cpu)
{
unsigned long lpar_rc;
OpenPOWER on IntegriCloud