diff options
author | Nathan Fontenot <nfont@austin.ibm.com> | 2008-07-23 14:27:30 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-07-25 01:44:41 -0400 |
commit | dfc3403f0e5ffb94ee29942f313b87d4061d951b (patch) | |
tree | 8e16a830d4869907f5f3b423dd400c927fcf8e4b | |
parent | 11529396ea3190113173f7a15e59a58dbcaa36c8 (diff) |
powerpc/pseries: Add memory entitlement capabilities to /proc/ppc64/lparcfg
Update /proc/ppc64/lparcfg to display Cooperative Memory
Overcommitment statistics as reported by the H_GET_MPP hcall. This
also updates the lparcfg interface to allow setting memory entitlement
and weight.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
Acked-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/lparcfg.c | 121 | ||||
-rw-r--r-- | include/asm-powerpc/hvcall.h | 18 |
2 files changed, 137 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index a0ca90ab5e39..86e5b3ed10d8 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <asm/prom.h> | 35 | #include <asm/prom.h> |
36 | #include <asm/vdso_datapage.h> | 36 | #include <asm/vdso_datapage.h> |
37 | 37 | ||
38 | #define MODULE_VERS "1.7" | 38 | #define MODULE_VERS "1.8" |
39 | #define MODULE_NAME "lparcfg" | 39 | #define MODULE_NAME "lparcfg" |
40 | 40 | ||
41 | /* #define LPARCFG_DEBUG */ | 41 | /* #define LPARCFG_DEBUG */ |
@@ -129,6 +129,35 @@ static int iseries_lparcfg_data(struct seq_file *m, void *v) | |||
129 | /* | 129 | /* |
130 | * Methods used to fetch LPAR data when running on a pSeries platform. | 130 | * Methods used to fetch LPAR data when running on a pSeries platform. |
131 | */ | 131 | */ |
132 | /** | ||
133 | * h_get_mpp | ||
134 | * H_GET_MPP hcall returns info in 7 parms | ||
135 | */ | ||
136 | int h_get_mpp(struct hvcall_mpp_data *mpp_data) | ||
137 | { | ||
138 | int rc; | ||
139 | unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; | ||
140 | |||
141 | rc = plpar_hcall9(H_GET_MPP, retbuf); | ||
142 | |||
143 | mpp_data->entitled_mem = retbuf[0]; | ||
144 | mpp_data->mapped_mem = retbuf[1]; | ||
145 | |||
146 | mpp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff; | ||
147 | mpp_data->pool_num = retbuf[2] & 0xffff; | ||
148 | |||
149 | mpp_data->mem_weight = (retbuf[3] >> 7 * 8) & 0xff; | ||
150 | mpp_data->unallocated_mem_weight = (retbuf[3] >> 6 * 8) & 0xff; | ||
151 | mpp_data->unallocated_entitlement = retbuf[3] & 0xffffffffffff; | ||
152 | |||
153 | mpp_data->pool_size = retbuf[4]; | ||
154 | mpp_data->loan_request = retbuf[5]; | ||
155 | mpp_data->backing_mem = retbuf[6]; | ||
156 | |||
157 | return rc; | ||
158 | } | ||
159 | EXPORT_SYMBOL(h_get_mpp); | ||
160 | |||
132 | /* | 161 | /* |
133 | * H_GET_PPP hcall returns info in 4 parms. | 162 | * H_GET_PPP hcall returns info in 4 parms. |
134 | * entitled_capacity,unallocated_capacity, | 163 | * entitled_capacity,unallocated_capacity, |
@@ -224,6 +253,44 @@ static void parse_ppp_data(struct seq_file *m) | |||
224 | seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated); | 253 | seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated); |
225 | } | 254 | } |
226 | 255 | ||
256 | /** | ||
257 | * parse_mpp_data | ||
258 | * Parse out data returned from h_get_mpp | ||
259 | */ | ||
260 | static void parse_mpp_data(struct seq_file *m) | ||
261 | { | ||
262 | struct hvcall_mpp_data mpp_data; | ||
263 | int rc; | ||
264 | |||
265 | rc = h_get_mpp(&mpp_data); | ||
266 | if (rc) | ||
267 | return; | ||
268 | |||
269 | seq_printf(m, "entitled_memory=%ld\n", mpp_data.entitled_mem); | ||
270 | |||
271 | if (mpp_data.mapped_mem != -1) | ||
272 | seq_printf(m, "mapped_entitled_memory=%ld\n", | ||
273 | mpp_data.mapped_mem); | ||
274 | |||
275 | seq_printf(m, "entitled_memory_group_number=%d\n", mpp_data.group_num); | ||
276 | seq_printf(m, "entitled_memory_pool_number=%d\n", mpp_data.pool_num); | ||
277 | |||
278 | seq_printf(m, "entitled_memory_weight=%d\n", mpp_data.mem_weight); | ||
279 | seq_printf(m, "unallocated_entitled_memory_weight=%d\n", | ||
280 | mpp_data.unallocated_mem_weight); | ||
281 | seq_printf(m, "unallocated_io_mapping_entitlement=%ld\n", | ||
282 | mpp_data.unallocated_entitlement); | ||
283 | |||
284 | if (mpp_data.pool_size != -1) | ||
285 | seq_printf(m, "entitled_memory_pool_size=%ld bytes\n", | ||
286 | mpp_data.pool_size); | ||
287 | |||
288 | seq_printf(m, "entitled_memory_loan_request=%ld\n", | ||
289 | mpp_data.loan_request); | ||
290 | |||
291 | seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem); | ||
292 | } | ||
293 | |||
227 | #define SPLPAR_CHARACTERISTICS_TOKEN 20 | 294 | #define SPLPAR_CHARACTERISTICS_TOKEN 20 |
228 | #define SPLPAR_MAXLENGTH 1026*(sizeof(char)) | 295 | #define SPLPAR_MAXLENGTH 1026*(sizeof(char)) |
229 | 296 | ||
@@ -351,6 +418,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
351 | /* this call handles the ibm,get-system-parameter contents */ | 418 | /* this call handles the ibm,get-system-parameter contents */ |
352 | parse_system_parameter_string(m); | 419 | parse_system_parameter_string(m); |
353 | parse_ppp_data(m); | 420 | parse_ppp_data(m); |
421 | parse_mpp_data(m); | ||
354 | 422 | ||
355 | seq_printf(m, "purr=%ld\n", get_purr()); | 423 | seq_printf(m, "purr=%ld\n", get_purr()); |
356 | } else { /* non SPLPAR case */ | 424 | } else { /* non SPLPAR case */ |
@@ -414,6 +482,43 @@ static ssize_t update_ppp(u64 *entitlement, u8 *weight) | |||
414 | return retval; | 482 | return retval; |
415 | } | 483 | } |
416 | 484 | ||
485 | /** | ||
486 | * update_mpp | ||
487 | * | ||
488 | * Update the memory entitlement and weight for the partition. Caller must | ||
489 | * specify either a new entitlement or weight, not both, to be updated | ||
490 | * since the h_set_mpp call takes both entitlement and weight as parameters. | ||
491 | */ | ||
492 | static ssize_t update_mpp(u64 *entitlement, u8 *weight) | ||
493 | { | ||
494 | struct hvcall_mpp_data mpp_data; | ||
495 | u64 new_entitled; | ||
496 | u8 new_weight; | ||
497 | ssize_t rc; | ||
498 | |||
499 | rc = h_get_mpp(&mpp_data); | ||
500 | if (rc) | ||
501 | return rc; | ||
502 | |||
503 | if (entitlement) { | ||
504 | new_weight = mpp_data.mem_weight; | ||
505 | new_entitled = *entitlement; | ||
506 | } else if (weight) { | ||
507 | new_weight = *weight; | ||
508 | new_entitled = mpp_data.entitled_mem; | ||
509 | } else | ||
510 | return -EINVAL; | ||
511 | |||
512 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", | ||
513 | __FUNCTION__, mpp_data.entitled_mem, mpp_data.mem_weight); | ||
514 | |||
515 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", | ||
516 | __FUNCTION__, new_entitled, new_weight); | ||
517 | |||
518 | rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight); | ||
519 | return rc; | ||
520 | } | ||
521 | |||
417 | /* | 522 | /* |
418 | * Interface for changing system parameters (variable capacity weight | 523 | * Interface for changing system parameters (variable capacity weight |
419 | * and entitled capacity). Format of input is "param_name=value"; | 524 | * and entitled capacity). Format of input is "param_name=value"; |
@@ -467,6 +572,20 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
467 | goto out; | 572 | goto out; |
468 | 573 | ||
469 | retval = update_ppp(NULL, new_weight_ptr); | 574 | retval = update_ppp(NULL, new_weight_ptr); |
575 | } else if (!strcmp(kbuf, "entitled_memory")) { | ||
576 | char *endp; | ||
577 | *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10); | ||
578 | if (endp == tmp) | ||
579 | goto out; | ||
580 | |||
581 | retval = update_mpp(new_entitled_ptr, NULL); | ||
582 | } else if (!strcmp(kbuf, "entitled_memory_weight")) { | ||
583 | char *endp; | ||
584 | *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10); | ||
585 | if (endp == tmp) | ||
586 | goto out; | ||
587 | |||
588 | retval = update_mpp(NULL, new_weight_ptr); | ||
470 | } else | 589 | } else |
471 | goto out; | 590 | goto out; |
472 | 591 | ||
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h index bf6cd7cb996c..46e76456cbbd 100644 --- a/include/asm-powerpc/hvcall.h +++ b/include/asm-powerpc/hvcall.h | |||
@@ -210,7 +210,9 @@ | |||
210 | #define H_JOIN 0x298 | 210 | #define H_JOIN 0x298 |
211 | #define H_VASI_STATE 0x2A4 | 211 | #define H_VASI_STATE 0x2A4 |
212 | #define H_ENABLE_CRQ 0x2B0 | 212 | #define H_ENABLE_CRQ 0x2B0 |
213 | #define MAX_HCALL_OPCODE H_ENABLE_CRQ | 213 | #define H_SET_MPP 0x2D0 |
214 | #define H_GET_MPP 0x2D4 | ||
215 | #define MAX_HCALL_OPCODE H_GET_MPP | ||
214 | 216 | ||
215 | #ifndef __ASSEMBLY__ | 217 | #ifndef __ASSEMBLY__ |
216 | 218 | ||
@@ -270,6 +272,20 @@ struct hcall_stats { | |||
270 | }; | 272 | }; |
271 | #define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) | 273 | #define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) |
272 | 274 | ||
275 | struct hvcall_mpp_data { | ||
276 | unsigned long entitled_mem; | ||
277 | unsigned long mapped_mem; | ||
278 | unsigned short group_num; | ||
279 | unsigned short pool_num; | ||
280 | unsigned char mem_weight; | ||
281 | unsigned char unallocated_mem_weight; | ||
282 | unsigned long unallocated_entitlement; /* value in bytes */ | ||
283 | unsigned long pool_size; | ||
284 | signed long loan_request; | ||
285 | unsigned long backing_mem; | ||
286 | }; | ||
287 | |||
288 | int h_get_mpp(struct hvcall_mpp_data *); | ||
273 | #endif /* __ASSEMBLY__ */ | 289 | #endif /* __ASSEMBLY__ */ |
274 | #endif /* __KERNEL__ */ | 290 | #endif /* __KERNEL__ */ |
275 | #endif /* _ASM_POWERPC_HVCALL_H */ | 291 | #endif /* _ASM_POWERPC_HVCALL_H */ |