21 #include <linux/module.h>
22 #include <linux/types.h>
23 #include <linux/errno.h>
27 #include <linux/slab.h>
28 #include <asm/uaccess.h>
35 #include <asm/vdso_datapage.h>
39 #define MODULE_VERS "1.9"
40 #define MODULE_NAME "lparcfg"
50 static unsigned long get_purr(
void)
52 unsigned long sum_purr = 0;
58 cu = &
per_cpu(cpu_usage_array, cpu);
59 sum_purr += cu->current_tb;
111 unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
113 rc = plpar_hcall9(H_GET_PPP, retbuf);
118 ppp_data->
group_num = (retbuf[2] >> 2 * 8) & 0xffff;
119 ppp_data->
pool_num = retbuf[2] & 0xffff;
121 ppp_data->
capped = (retbuf[3] >> 6 * 8) & 0x01;
122 ppp_data->
weight = (retbuf[3] >> 5 * 8) & 0xff;
134 static unsigned h_pic(
unsigned long *pool_idle_time,
135 unsigned long *num_procs)
138 unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
140 rc = plpar_hcall(H_PIC, retbuf);
142 *pool_idle_time = retbuf[0];
143 *num_procs = retbuf[1];
152 static void parse_ppp_data(
struct seq_file *
m)
159 rc = h_get_ppp(&ppp_data);
163 seq_printf(m,
"partition_entitled_capacity=%lld\n",
164 ppp_data.entitlement);
165 seq_printf(m,
"group=%d\n", ppp_data.group_num);
166 seq_printf(m,
"system_active_processors=%d\n",
167 ppp_data.active_system_procs);
170 if (lppaca_of(0).shared_proc) {
171 unsigned long pool_idle_time, pool_procs;
173 seq_printf(m,
"pool=%d\n", ppp_data.pool_num);
177 ppp_data.active_procs_in_pool * 100);
179 h_pic(&pool_idle_time, &pool_procs);
180 seq_printf(m,
"pool_idle_time=%ld\n", pool_idle_time);
181 seq_printf(m,
"pool_num_procs=%ld\n", pool_procs);
184 seq_printf(m,
"unallocated_capacity_weight=%d\n",
185 ppp_data.unallocated_weight);
186 seq_printf(m,
"capacity_weight=%d\n", ppp_data.weight);
187 seq_printf(m,
"capped=%d\n", ppp_data.capped);
189 ppp_data.unallocated_entitlement);
198 "ibm,partition-performance-parameters-level",
200 if (perf_level && (*perf_level >= 1)) {
202 "physical_procs_allocated_to_virtualization=%d\n",
203 ppp_data.phys_platform_procs);
204 seq_printf(m,
"max_proc_capacity_available=%d\n",
205 ppp_data.max_proc_cap_avail);
206 seq_printf(m,
"entitled_proc_capacity_available=%d\n",
207 ppp_data.entitled_proc_cap_avail);
218 static void parse_mpp_data(
struct seq_file *m)
220 struct hvcall_mpp_data mpp_data;
227 seq_printf(m,
"entitled_memory=%ld\n", mpp_data.entitled_mem);
229 if (mpp_data.mapped_mem != -1)
231 mpp_data.mapped_mem);
233 seq_printf(m,
"entitled_memory_group_number=%d\n", mpp_data.group_num);
234 seq_printf(m,
"entitled_memory_pool_number=%d\n", mpp_data.pool_num);
236 seq_printf(m,
"entitled_memory_weight=%d\n", mpp_data.mem_weight);
237 seq_printf(m,
"unallocated_entitled_memory_weight=%d\n",
238 mpp_data.unallocated_mem_weight);
239 seq_printf(m,
"unallocated_io_mapping_entitlement=%ld\n",
240 mpp_data.unallocated_entitlement);
242 if (mpp_data.pool_size != -1)
243 seq_printf(m,
"entitled_memory_pool_size=%ld bytes\n",
246 seq_printf(m,
"entitled_memory_loan_request=%ld\n",
247 mpp_data.loan_request);
249 seq_printf(m,
"backing_memory=%ld bytes\n", mpp_data.backing_mem);
256 static void parse_mpp_x_data(
struct seq_file *m)
258 struct hvcall_mpp_x_data mpp_x_data;
260 if (!firmware_has_feature(FW_FEATURE_XCMO))
265 seq_printf(m,
"coalesced_bytes=%ld\n", mpp_x_data.coalesced_bytes);
267 if (mpp_x_data.pool_coalesced_bytes)
269 mpp_x_data.pool_coalesced_bytes);
270 if (mpp_x_data.pool_purr_cycles)
271 seq_printf(m,
"coalesce_pool_purr=%ld\n", mpp_x_data.pool_purr_cycles);
272 if (mpp_x_data.pool_spurr_cycles)
273 seq_printf(m,
"coalesce_pool_spurr=%ld\n", mpp_x_data.pool_spurr_cycles);
276 #define SPLPAR_CHARACTERISTICS_TOKEN 20
277 #define SPLPAR_MAXLENGTH 1026*(sizeof(char))
285 static void parse_system_parameter_string(
struct seq_file *m)
292 __FILE__, __func__, __LINE__);
296 spin_lock(&rtas_data_buf_lock);
304 spin_unlock(&rtas_data_buf_lock);
306 if (call_status != 0) {
308 "%s %s Error calling get-system-parameter (0x%x)\n",
309 __FILE__, __func__, call_status);
316 __FILE__, __func__, __LINE__);
323 splpar_strlen = local_buffer[0] * 256 + local_buffer[1];
328 while ((*local_buffer) && (idx < splpar_strlen)) {
329 workbuffer[w_idx++] = local_buffer[idx++];
330 if ((local_buffer[idx] ==
',')
331 || (local_buffer[idx] ==
'\0')) {
332 workbuffer[w_idx] =
'\0';
340 }
else if (local_buffer[idx] ==
'=') {
343 if (0 ==
strcmp(workbuffer,
"MaxEntCap")) {
345 "partition_max_entitled_capacity");
346 w_idx =
strlen(workbuffer);
348 if (0 ==
strcmp(workbuffer,
"MaxPlatProcs")) {
350 "system_potential_processors");
351 w_idx =
strlen(workbuffer);
365 static int lparcfg_count_active_processors(
void)
379 static void pseries_cmo_data(
struct seq_file *m)
382 unsigned long cmo_faults = 0;
383 unsigned long cmo_fault_time = 0;
385 seq_printf(m,
"cmo_enabled=%d\n", firmware_has_feature(FW_FEATURE_CMO));
387 if (!firmware_has_feature(FW_FEATURE_CMO))
391 cmo_faults += lppaca_of(cpu).cmo_faults;
392 cmo_fault_time += lppaca_of(cpu).cmo_fault_time;
395 seq_printf(m,
"cmo_faults=%lu\n", cmo_faults);
398 seq_printf(m,
"cmo_primary_psp=%d\n", cmo_get_primary_psp());
399 seq_printf(m,
"cmo_secondary_psp=%d\n", cmo_get_secondary_psp());
400 seq_printf(m,
"cmo_page_size=%lu\n", cmo_get_page_size());
403 static void splpar_dispatch_data(
struct seq_file *m)
406 unsigned long dispatches = 0;
407 unsigned long dispatch_dispersions = 0;
410 dispatches += lppaca_of(cpu).yield_count;
411 dispatch_dispersions += lppaca_of(cpu).dispersion_count;
414 seq_printf(m,
"dispatches=%lu\n", dispatches);
415 seq_printf(m,
"dispatch_dispersions=%lu\n", dispatch_dispersions);
418 static void parse_em_data(
struct seq_file *m)
420 unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
422 if (plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
423 seq_printf(m,
"power_mode_data=%016lx\n", retbuf[0]);
426 static int pseries_lparcfg_data(
struct seq_file *m,
void *
v)
428 int partition_potential_processors;
429 int partition_active_processors;
431 const int *lrdrp =
NULL;
438 partition_potential_processors =
vdso_data->processorCount;
440 partition_potential_processors = *(lrdrp + 4);
442 of_node_put(rtas_node);
444 partition_active_processors = lparcfg_count_active_processors();
446 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
448 parse_system_parameter_string(m);
453 splpar_dispatch_data(m);
458 seq_printf(m,
"system_active_processors=%d\n",
459 partition_potential_processors);
461 seq_printf(m,
"system_potential_processors=%d\n",
462 partition_potential_processors);
464 seq_printf(m,
"partition_max_entitled_capacity=%d\n",
465 partition_potential_processors * 100);
467 seq_printf(m,
"partition_entitled_capacity=%d\n",
468 partition_active_processors * 100);
471 seq_printf(m,
"partition_active_processors=%d\n",
472 partition_active_processors);
474 seq_printf(m,
"partition_potential_processors=%d\n",
475 partition_potential_processors);
477 seq_printf(m,
"shared_processor_mode=%d\n", lppaca_of(0).shared_proc);
494 retval = h_get_ppp(&ppp_data);
499 new_weight = ppp_data.weight;
503 new_entitled = ppp_data.entitlement;
507 pr_debug(
"%s: current_entitled = %llu, current_weight = %u\n",
508 __func__, ppp_data.entitlement, ppp_data.weight);
510 pr_debug(
"%s: new_entitled = %llu, new_weight = %u\n",
511 __func__, new_entitled, new_weight);
513 retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight);
526 struct hvcall_mpp_data mpp_data;
545 new_weight = mpp_data.mem_weight;
546 new_entitled = *entitlement;
549 new_entitled = mpp_data.entitled_mem;
553 pr_debug(
"%s: current_entitled = %lu, current_weight = %u\n",
554 __func__, mpp_data.entitled_mem, mpp_data.mem_weight);
556 pr_debug(
"%s: new_entitled = %llu, new_weight = %u\n",
557 __func__, new_entitled, new_weight);
559 rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight);
574 size_t count, loff_t * off)
579 u64 new_entitled, *new_entitled_ptr = &new_entitled;
580 u8 new_weight, *new_weight_ptr = &new_weight;
583 if (!firmware_has_feature(FW_FEATURE_SPLPAR))
592 kbuf[count - 1] =
'\0';
599 if (!
strcmp(kbuf,
"partition_entitled_capacity")) {
605 retval = update_ppp(new_entitled_ptr,
NULL);
606 }
else if (!
strcmp(kbuf,
"capacity_weight")) {
612 retval = update_ppp(
NULL, new_weight_ptr);
613 }
else if (!
strcmp(kbuf,
"entitled_memory")) {
619 retval = update_mpp(new_entitled_ptr,
NULL);
620 }
else if (!
strcmp(kbuf,
"entitled_memory_weight")) {
626 retval = update_mpp(
NULL, new_weight_ptr);
630 if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
632 }
else if (retval == H_BUSY) {
634 }
else if (retval == H_HARDWARE) {
636 }
else if (retval == H_PARAMETER) {
643 static int lparcfg_data(
struct seq_file *m,
void *v)
646 const char *
model =
"";
647 const char *system_id =
"";
649 const unsigned int *lp_index_ptr;
650 unsigned int lp_index = 0;
665 lp_index = *lp_index_ptr;
668 seq_printf(m,
"serial_number=%s\n", system_id);
670 seq_printf(m,
"partition_id=%d\n", (
int)lp_index);
672 return pseries_lparcfg_data(m, v);
675 static int lparcfg_open(
struct inode *
inode,
struct file *file)
683 .write = lparcfg_write,
684 .open = lparcfg_open,
689 static int __init lparcfg_init(
void)
695 if (firmware_has_feature(FW_FEATURE_SPLPAR))
698 ent = proc_create(
"powerpc/lparcfg", mode,
NULL, &lparcfg_fops);
704 proc_ppc64_lparcfg = ent;
708 static void __exit lparcfg_cleanup(
void)
710 if (proc_ppc64_lparcfg)