Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b4aea36b7956eeebfc56314ce0944db1441255ce
Commit:     b4aea36b7956eeebfc56314ce0944db1441255ce
Parent:     f144e7c7272bf527c380bffaa5e789dc28a09d8d
Author:     Mohan Kumar M <[EMAIL PROTECTED]>
AuthorDate: Wed Mar 21 11:21:32 2007 +0530
Committer:  Paul Mackerras <[EMAIL PROTECTED]>
CommitDate: Thu Mar 22 15:01:43 2007 +1100

    [POWERPC] Avoid hypervisor statistics calculation in real mode
    
    kexec invokes plpar_hcall hypervisor call in real mode.  plpar_hcall
    refers to per cpu variables for accounting hypervisor statistics.
    These variables may not be in the RMO region, so accesses to them
    in real mode may result in a data storage exception.
    
    This fixes this problem by using a new plpar_hcall_raw function which
    does not update the hypervisor call statistics.  Thanks to Anton for
    suggesting this idea.
    
    Signed-off-by: Mohan Kumar M <[EMAIL PROTECTED]>
    Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
---
 arch/powerpc/platforms/pseries/hvCall.S         |   34 +++++++++++++++++++++++
 arch/powerpc/platforms/pseries/lpar.c           |    2 +-
 arch/powerpc/platforms/pseries/plpar_wrappers.h |   16 +++++++++++
 include/asm-powerpc/hvcall.h                    |   14 +++++++++
 4 files changed, 65 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/hvCall.S 
b/arch/powerpc/platforms/pseries/hvCall.S
index 5c7e387..1501b0a 100644
--- a/arch/powerpc/platforms/pseries/hvCall.S
+++ b/arch/powerpc/platforms/pseries/hvCall.S
@@ -123,6 +123,40 @@ _GLOBAL(plpar_hcall)
 
        blr                             /* return r3 = status */
 
+/*
+ * plpar_hcall_raw can be called in real mode. kexec/kdump need some
+ * hypervisor calls to be executed in real mode. So plpar_hcall_raw
+ * does not access the per cpu hypervisor call statistics variables,
+ * since these variables may not be present in the RMO region.
+ */
+_GLOBAL(plpar_hcall_raw)
+       HMT_MEDIUM
+
+       mfcr    r0
+       stw     r0,8(r1)
+
+       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
+
+       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)
+       mtcrf   0xff,r0
+
+       blr                             /* return r3 = status */
+
 _GLOBAL(plpar_hcall9)
        HMT_MEDIUM
 
diff --git a/arch/powerpc/platforms/pseries/lpar.c 
b/arch/powerpc/platforms/pseries/lpar.c
index 7496005..843ee96 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -378,7 +378,7 @@ static void pSeries_lpar_hptab_clear(void)
 
        /* TODO: Use bulk call */
        for (i = 0; i < hpte_count; i++)
-               plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
+               plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2);
 }
 
 /*
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h 
b/arch/powerpc/platforms/pseries/plpar_wrappers.h
index 3eb7b29..2e4d10c 100644
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
@@ -78,6 +78,22 @@ static inline long plpar_pte_remove(unsigned long flags, 
unsigned long ptex,
        return rc;
 }
 
+/* plpar_pte_remove_raw can be called in real mode. It calls plpar_hcall_raw */
+static inline long plpar_pte_remove_raw(unsigned long flags, unsigned long 
ptex,
+               unsigned long avpn, unsigned long *old_pteh_ret,
+               unsigned long *old_ptel_ret)
+{
+       long rc;
+       unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+       rc = plpar_hcall_raw(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)
 {
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 6097780..62efd9d 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -237,6 +237,20 @@ long plpar_hcall_norets(unsigned long opcode, ...);
 long plpar_hcall(unsigned long opcode, unsigned long *retbuf, ...);
 
 /**
+ * plpar_hcall_raw: - Make a hypervisor call without calculating hcall stats
+ * @opcode: The hypervisor call to make.
+ * @retbuf: Buffer to store up to 4 return arguments in.
+ *
+ * This call supports up to 6 arguments and 4 return arguments. Use
+ * PLPAR_HCALL_BUFSIZE to size the return argument buffer.
+ *
+ * Used when phyp interface needs to be called in real mode. Similar to
+ * plpar_hcall, but plpar_hcall_raw works in real mode and does not
+ * calculate hypervisor call statistics.
+ */
+long plpar_hcall_raw(unsigned long opcode, unsigned long *retbuf, ...);
+
+/**
  * plpar_hcall9: - Make a pseries hypervisor call with up to 9 return arguments
  * @opcode: The hypervisor call to make.
  * @retbuf: Buffer to store up to 9 return arguments in.
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to