Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * This file contains the generic code to perform a call to the |
3 | * pSeries LPAR hypervisor. | |
1da177e4 LT |
4 | * |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License | |
7 | * as published by the Free Software Foundation; either version | |
8 | * 2 of the License, or (at your option) any later version. | |
9 | */ | |
10 | #include <asm/hvcall.h> | |
11 | #include <asm/processor.h> | |
12 | #include <asm/ppc_asm.h> | |
57852a85 | 13 | #include <asm/asm-offsets.h> |
1da177e4 LT |
14 | |
15 | #define STK_PARM(i) (48 + ((i)-3)*8) | |
16 | ||
57852a85 MK |
17 | #ifdef CONFIG_HCALL_STATS |
18 | /* | |
19 | * precall must preserve all registers. use unused STK_PARM() | |
20 | * areas to save snapshots and opcode. | |
21 | */ | |
22 | #define HCALL_INST_PRECALL \ | |
23 | std r3,STK_PARM(r3)(r1); /* save opcode */ \ | |
24 | mftb r0; /* get timebase and */ \ | |
25 | std r0,STK_PARM(r5)(r1); /* save for later */ \ | |
26 | BEGIN_FTR_SECTION; \ | |
27 | mfspr r0,SPRN_PURR; /* get PURR and */ \ | |
28 | std r0,STK_PARM(r6)(r1); /* save for later */ \ | |
dc40127c | 29 | END_FTR_SECTION_IFSET(CPU_FTR_PURR); |
57852a85 MK |
30 | |
31 | /* | |
32 | * postcall is performed immediately before function return which | |
33 | * allows liberal use of volatile registers. | |
34 | */ | |
35 | #define HCALL_INST_POSTCALL \ | |
36 | ld r4,STK_PARM(r3)(r1); /* validate opcode */ \ | |
37 | cmpldi cr7,r4,MAX_HCALL_OPCODE; \ | |
38 | bgt- cr7,1f; \ | |
39 | \ | |
40 | /* get time and PURR snapshots after hcall */ \ | |
41 | mftb r7; /* timebase after */ \ | |
42 | BEGIN_FTR_SECTION; \ | |
43 | mfspr r8,SPRN_PURR; /* PURR after */ \ | |
44 | ld r6,STK_PARM(r6)(r1); /* PURR before */ \ | |
45 | subf r6,r6,r8; /* delta */ \ | |
dc40127c | 46 | END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ |
57852a85 MK |
47 | ld r5,STK_PARM(r5)(r1); /* timebase before */ \ |
48 | subf r5,r5,r7; /* time delta */ \ | |
49 | \ | |
50 | /* calculate address of stat structure r4 = opcode */ \ | |
51 | srdi r4,r4,2; /* index into array */ \ | |
52 | mulli r4,r4,HCALL_STAT_SIZE; \ | |
53 | LOAD_REG_ADDR(r7, per_cpu__hcall_stats); \ | |
54 | add r4,r4,r7; \ | |
55 | ld r7,PACA_DATA_OFFSET(r13); /* per cpu offset */ \ | |
56 | add r4,r4,r7; \ | |
57 | \ | |
58 | /* update stats */ \ | |
59 | ld r7,HCALL_STAT_CALLS(r4); /* count */ \ | |
60 | addi r7,r7,1; \ | |
61 | std r7,HCALL_STAT_CALLS(r4); \ | |
62 | ld r7,HCALL_STAT_TB(r4); /* timebase */ \ | |
63 | add r7,r7,r5; \ | |
64 | std r7,HCALL_STAT_TB(r4); \ | |
65 | BEGIN_FTR_SECTION; \ | |
66 | ld r7,HCALL_STAT_PURR(r4); /* PURR */ \ | |
67 | add r7,r7,r6; \ | |
68 | std r7,HCALL_STAT_PURR(r4); \ | |
dc40127c | 69 | END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ |
57852a85 MK |
70 | 1: |
71 | #else | |
72 | #define HCALL_INST_PRECALL | |
73 | #define HCALL_INST_POSTCALL | |
74 | #endif | |
75 | ||
1da177e4 LT |
76 | .text |
77 | ||
1da177e4 | 78 | _GLOBAL(plpar_hcall_norets) |
eeb24de4 AB |
79 | HMT_MEDIUM |
80 | ||
1da177e4 LT |
81 | mfcr r0 |
82 | stw r0,8(r1) | |
83 | ||
57852a85 MK |
84 | HCALL_INST_PRECALL |
85 | ||
1da177e4 LT |
86 | HVSC /* invoke the hypervisor */ |
87 | ||
57852a85 MK |
88 | HCALL_INST_POSTCALL |
89 | ||
1da177e4 LT |
90 | lwz r0,8(r1) |
91 | mtcrf 0xff,r0 | |
92 | blr /* return r3 = status */ | |
93 | ||
b9377ffc | 94 | _GLOBAL(plpar_hcall) |
eeb24de4 AB |
95 | HMT_MEDIUM |
96 | ||
1da177e4 | 97 | mfcr r0 |
1da177e4 LT |
98 | stw r0,8(r1) |
99 | ||
57852a85 MK |
100 | HCALL_INST_PRECALL |
101 | ||
b9377ffc | 102 | std r4,STK_PARM(r4)(r1) /* Save ret buffer */ |
1da177e4 | 103 | |
b9377ffc AB |
104 | mr r4,r5 |
105 | mr r5,r6 | |
106 | mr r6,r7 | |
107 | mr r7,r8 | |
108 | mr r8,r9 | |
109 | mr r9,r10 | |
1da177e4 LT |
110 | |
111 | HVSC /* invoke the hypervisor */ | |
112 | ||
b9377ffc AB |
113 | ld r12,STK_PARM(r4)(r1) |
114 | std r4, 0(r12) | |
115 | std r5, 8(r12) | |
116 | std r6, 16(r12) | |
117 | std r7, 24(r12) | |
b13a96cf | 118 | |
57852a85 MK |
119 | HCALL_INST_POSTCALL |
120 | ||
b13a96cf | 121 | lwz r0,8(r1) |
b13a96cf HS |
122 | mtcrf 0xff,r0 |
123 | ||
124 | blr /* return r3 = status */ | |
125 | ||
b9377ffc | 126 | _GLOBAL(plpar_hcall9) |
b13a96cf HS |
127 | HMT_MEDIUM |
128 | ||
129 | mfcr r0 | |
130 | stw r0,8(r1) | |
131 | ||
57852a85 MK |
132 | HCALL_INST_PRECALL |
133 | ||
b9377ffc AB |
134 | std r4,STK_PARM(r4)(r1) /* Save ret buffer */ |
135 | ||
136 | mr r4,r5 | |
137 | mr r5,r6 | |
138 | mr r6,r7 | |
139 | mr r7,r8 | |
140 | mr r8,r9 | |
141 | mr r9,r10 | |
142 | ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ | |
143 | ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ | |
144 | ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ | |
b13a96cf HS |
145 | |
146 | HVSC /* invoke the hypervisor */ | |
147 | ||
ab87e8dc | 148 | mr r0,r12 |
b9377ffc AB |
149 | ld r12,STK_PARM(r4)(r1) |
150 | std r4, 0(r12) | |
151 | std r5, 8(r12) | |
152 | std r6, 16(r12) | |
153 | std r7, 24(r12) | |
154 | std r8, 32(r12) | |
155 | std r9, 40(r12) | |
156 | std r10,48(r12) | |
157 | std r11,56(r12) | |
ab87e8dc | 158 | std r0, 64(r12) |
b13a96cf | 159 | |
57852a85 MK |
160 | HCALL_INST_POSTCALL |
161 | ||
b13a96cf HS |
162 | lwz r0,8(r1) |
163 | mtcrf 0xff,r0 | |
164 | ||
165 | blr /* return r3 = status */ |