[RFC] asm code for Hypervisor Call Instrumentation
From: Mike Kravetz <hidden>
Date: 2006-08-02 17:59:33
In my last submission of hcall instrumentation patches, I took
Paul's suggestion and added code to get the timebase and PURR
snapshots in the hcall asm routines. I'm not confident in my
assembly skills, so I would really like some comments on this
approach/code. The idea(and some code) was taken from hash_low_64.S.
Of course, this all 'appears' to work correctly. :)
This patch is built on top of Anton's hcall cleanup patch. One
remaining issue is 'where should the statistic data structures
be updated?'. For simplicity, I have the asm code call the
following C routine to perform the updates.
void update_hcall_stats(unsigned long opcode, unsigned long tb_delta,
unsigned long purr_delta)
{
unsigned long op_index = opcode >> 2;
struct hcall_stats *hs = &__get_cpu_var(hcall_stats[op_index]);
hs->tb_total += tb_delta;
hs->purr_total += purr_delta;
hs->num_calls++;
}
I honestly do not know if it would be better to do all of this in the
assembly routine. I believe that 'allocation' of a stack frame is
only necessary because of the callout. Right?
--
Mike
diff -Naupr powerpc/arch/powerpc/platforms/pseries/hvCall.S powerpc.work/arch/powerpc/platforms/pseries/hvCall.S--- powerpc/arch/powerpc/platforms/pseries/hvCall.S 2006-07-19 18:58:18.000000000 +0000
+++ powerpc.work/arch/powerpc/platforms/pseries/hvCall.S 2006-07-21 07:06:49.000000000 +0000@@ -11,7 +11,57 @@ #include <asm/processor.h> #include <asm/ppc_asm.h> -#define STK_PARM(i) (48 + ((i)-3)*8) +#define STK_PARM(i) (STACKFRAMESIZE + 48 + ((i)-3)*8) +#define STK_REG(i) (112 + ((i)-14)*8) + +#ifdef CONFIG_HCALL_STATS +#define STACKFRAMESIZE 256 +#define HCALL_INST_PRECALL \ + /* use stack frame to save a few non-volital regs */ \ + stdu r1,-STACKFRAMESIZE(r1); \ + std r31,STK_REG(r31)(r1); \ + std r30,STK_REG(r30)(r1); \ + std r29,STK_REG(r29)(r1); \ + std r28,STK_REG(r28)(r1); \ + \ + /* save lr and hcall opcode */ \ + /* then get time, purr snapshot before hcall */ \ + mflr r31; \ + mr r30,r3; \ + mftb r29; \ +BEGIN_FTR_SECTION; \ + mfspr r28,SPRN_PURR; \ +END_FTR_SECTION_IFSET(CPU_FTR_PURR); + +#define HCALL_INST_POSTCALL \ + /* get time, purr snapshot after hcall */ \ + mftb r4; \ +BEGIN_FTR_SECTION; \ + mfspr r5,SPRN_PURR; \ +END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ + \ + /* setup regs to call routine that stuffs stats */ \ + /* into per-cpu/per-call structure. */ \ + subf r4,r29,r4; \ + subf r5,r28,r5; \ + mr r29,r3; /* save hcall rc */ \ + mr r3,r30; \ + bl .update_hcall_stats; \ + \ + /* restore hcall rc, lr and non-volital regs */ \ + mr r3,r29; \ + mtlr r31; \ + ld r31,STK_REG(r31)(r1); \ + ld r30,STK_REG(r30)(r1); \ + ld r29,STK_REG(r29)(r1); \ + ld r28,STK_REG(r28)(r1); \ + addi r1,r1,STACKFRAMESIZE +#else + +#define STACKFRAMESIZE 0 +#define HCALL_INST_PRECALL nop +#define HCALL_INST_POSTCALL nop +#endif .text
@@ -21,8 +71,12 @@ _GLOBAL(plpar_hcall_norets) mfcr r0 stw r0,8(r1) + HCALL_INST_PRECALL + HVSC /* invoke the hypervisor */ + HCALL_INST_POSTCALL + lwz r0,8(r1) mtcrf 0xff,r0 blr /* return r3 = status */
@@ -33,6 +87,8 @@ _GLOBAL(plpar_hcall) mfcr r0 stw r0,8(r1) + HCALL_INST_PRECALL + std r4,STK_PARM(r4)(r1) /* Save ret buffer */ mr r4,r5
@@ -50,6 +106,8 @@ _GLOBAL(plpar_hcall) std r6, 16(r12) std r7, 24(r12) + HCALL_INST_POSTCALL + lwz r0,8(r1) mtcrf 0xff,r0
@@ -61,6 +119,8 @@ _GLOBAL(plpar_hcall9) mfcr r0 stw r0,8(r1) + HCALL_INST_PRECALL + std r4,STK_PARM(r4)(r1) /* Save ret buffer */ mr r4,r5
@@ -86,6 +146,8 @@ _GLOBAL(plpar_hcall9) std r11,56(r12) std r12,64(r12) + HCALL_INST_POSTCALL + lwz r0,8(r1) mtcrf 0xff,r0