GNU Linux-libre 5.19-rc6-gnu
[releases.git] / arch / powerpc / platforms / pseries / lparcfg.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * PowerPC64 LPAR Configuration Information Driver
4  *
5  * Dave Engebretsen engebret@us.ibm.com
6  *    Copyright (c) 2003 Dave Engebretsen
7  * Will Schmidt willschm@us.ibm.com
8  *    SPLPAR updates, Copyright (c) 2003 Will Schmidt IBM Corporation.
9  *    seq_file updates, Copyright (c) 2004 Will Schmidt IBM Corporation.
10  * Nathan Lynch nathanl@austin.ibm.com
11  *    Added lparcfg_write, Copyright (C) 2004 Nathan Lynch IBM Corporation.
12  *
13  * This driver creates a proc file at /proc/ppc64/lparcfg which contains
14  * keyword - value pairs that specify the configuration of the partition.
15  */
16
17 #include <linux/module.h>
18 #include <linux/types.h>
19 #include <linux/errno.h>
20 #include <linux/proc_fs.h>
21 #include <linux/init.h>
22 #include <linux/seq_file.h>
23 #include <linux/slab.h>
24 #include <linux/uaccess.h>
25 #include <linux/hugetlb.h>
26 #include <asm/lppaca.h>
27 #include <asm/hvcall.h>
28 #include <asm/firmware.h>
29 #include <asm/rtas.h>
30 #include <asm/time.h>
31 #include <asm/vdso_datapage.h>
32 #include <asm/vio.h>
33 #include <asm/mmu.h>
34 #include <asm/machdep.h>
35 #include <asm/drmem.h>
36
37 #include "pseries.h"
38
39 /*
40  * This isn't a module but we expose that to userspace
41  * via /proc so leave the definitions here
42  */
43 #define MODULE_VERS "1.9"
44 #define MODULE_NAME "lparcfg"
45
46 /* #define LPARCFG_DEBUG */
47
48 /*
49  * Track sum of all purrs across all processors. This is used to further
50  * calculate usage values by different applications
51  */
52 static void cpu_get_purr(void *arg)
53 {
54         atomic64_t *sum = arg;
55
56         atomic64_add(mfspr(SPRN_PURR), sum);
57 }
58
59 static unsigned long get_purr(void)
60 {
61         atomic64_t purr = ATOMIC64_INIT(0);
62
63         on_each_cpu(cpu_get_purr, &purr, 1);
64
65         return atomic64_read(&purr);
66 }
67
68 /*
69  * Methods used to fetch LPAR data when running on a pSeries platform.
70  */
71
72 struct hvcall_ppp_data {
73         u64     entitlement;
74         u64     unallocated_entitlement;
75         u16     group_num;
76         u16     pool_num;
77         u8      capped;
78         u8      weight;
79         u8      unallocated_weight;
80         u16     active_procs_in_pool;
81         u16     active_system_procs;
82         u16     phys_platform_procs;
83         u32     max_proc_cap_avail;
84         u32     entitled_proc_cap_avail;
85 };
86
87 /*
88  * H_GET_PPP hcall returns info in 4 parms.
89  *  entitled_capacity,unallocated_capacity,
90  *  aggregation, resource_capability).
91  *
92  *  R4 = Entitled Processor Capacity Percentage.
93  *  R5 = Unallocated Processor Capacity Percentage.
94  *  R6 (AABBCCDDEEFFGGHH).
95  *      XXXX - reserved (0)
96  *          XXXX - reserved (0)
97  *              XXXX - Group Number
98  *                  XXXX - Pool Number.
99  *  R7 (IIJJKKLLMMNNOOPP).
100  *      XX - reserved. (0)
101  *        XX - bit 0-6 reserved (0).   bit 7 is Capped indicator.
102  *          XX - variable processor Capacity Weight
103  *            XX - Unallocated Variable Processor Capacity Weight.
104  *              XXXX - Active processors in Physical Processor Pool.
105  *                  XXXX  - Processors active on platform.
106  *  R8 (QQQQRRRRRRSSSSSS). if ibm,partition-performance-parameters-level >= 1
107  *      XXXX - Physical platform procs allocated to virtualization.
108  *          XXXXXX - Max procs capacity % available to the partitions pool.
109  *                XXXXXX - Entitled procs capacity % available to the
110  *                         partitions pool.
111  */
112 static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data)
113 {
114         unsigned long rc;
115         unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
116
117         rc = plpar_hcall9(H_GET_PPP, retbuf);
118
119         ppp_data->entitlement = retbuf[0];
120         ppp_data->unallocated_entitlement = retbuf[1];
121
122         ppp_data->group_num = (retbuf[2] >> 2 * 8) & 0xffff;
123         ppp_data->pool_num = retbuf[2] & 0xffff;
124
125         ppp_data->capped = (retbuf[3] >> 6 * 8) & 0x01;
126         ppp_data->weight = (retbuf[3] >> 5 * 8) & 0xff;
127         ppp_data->unallocated_weight = (retbuf[3] >> 4 * 8) & 0xff;
128         ppp_data->active_procs_in_pool = (retbuf[3] >> 2 * 8) & 0xffff;
129         ppp_data->active_system_procs = retbuf[3] & 0xffff;
130
131         ppp_data->phys_platform_procs = retbuf[4] >> 6 * 8;
132         ppp_data->max_proc_cap_avail = (retbuf[4] >> 3 * 8) & 0xffffff;
133         ppp_data->entitled_proc_cap_avail = retbuf[4] & 0xffffff;
134
135         return rc;
136 }
137
138 static void show_gpci_data(struct seq_file *m)
139 {
140         struct hv_gpci_request_buffer *buf;
141         unsigned int affinity_score;
142         long ret;
143
144         buf = kmalloc(sizeof(*buf), GFP_KERNEL);
145         if (buf == NULL)
146                 return;
147
148         /*
149          * Show the local LPAR's affinity score.
150          *
151          * 0xB1 selects the Affinity_Domain_Info_By_Partition subcall.
152          * The score is at byte 0xB in the output buffer.
153          */
154         memset(&buf->params, 0, sizeof(buf->params));
155         buf->params.counter_request = cpu_to_be32(0xB1);
156         buf->params.starting_index = cpu_to_be32(-1);   /* local LPAR */
157         buf->params.counter_info_version_in = 0x5;      /* v5+ for score */
158         ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, virt_to_phys(buf),
159                                  sizeof(*buf));
160         if (ret != H_SUCCESS) {
161                 pr_debug("hcall failed: H_GET_PERF_COUNTER_INFO: %ld, %x\n",
162                          ret, be32_to_cpu(buf->params.detail_rc));
163                 goto out;
164         }
165         affinity_score = buf->bytes[0xB];
166         seq_printf(m, "partition_affinity_score=%u\n", affinity_score);
167 out:
168         kfree(buf);
169 }
170
171 static unsigned h_pic(unsigned long *pool_idle_time,
172                       unsigned long *num_procs)
173 {
174         unsigned long rc;
175         unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
176
177         rc = plpar_hcall(H_PIC, retbuf);
178
179         *pool_idle_time = retbuf[0];
180         *num_procs = retbuf[1];
181
182         return rc;
183 }
184
185 /*
186  * parse_ppp_data
187  * Parse out the data returned from h_get_ppp and h_pic
188  */
189 static void parse_ppp_data(struct seq_file *m)
190 {
191         struct hvcall_ppp_data ppp_data;
192         struct device_node *root;
193         const __be32 *perf_level;
194         int rc;
195
196         rc = h_get_ppp(&ppp_data);
197         if (rc)
198                 return;
199
200         seq_printf(m, "partition_entitled_capacity=%lld\n",
201                    ppp_data.entitlement);
202         seq_printf(m, "group=%d\n", ppp_data.group_num);
203         seq_printf(m, "system_active_processors=%d\n",
204                    ppp_data.active_system_procs);
205
206         /* pool related entries are appropriate for shared configs */
207         if (lppaca_shared_proc(get_lppaca())) {
208                 unsigned long pool_idle_time, pool_procs;
209
210                 seq_printf(m, "pool=%d\n", ppp_data.pool_num);
211
212                 /* report pool_capacity in percentage */
213                 seq_printf(m, "pool_capacity=%d\n",
214                            ppp_data.active_procs_in_pool * 100);
215
216                 h_pic(&pool_idle_time, &pool_procs);
217                 seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
218                 seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
219         }
220
221         seq_printf(m, "unallocated_capacity_weight=%d\n",
222                    ppp_data.unallocated_weight);
223         seq_printf(m, "capacity_weight=%d\n", ppp_data.weight);
224         seq_printf(m, "capped=%d\n", ppp_data.capped);
225         seq_printf(m, "unallocated_capacity=%lld\n",
226                    ppp_data.unallocated_entitlement);
227
228         /* The last bits of information returned from h_get_ppp are only
229          * valid if the ibm,partition-performance-parameters-level
230          * property is >= 1.
231          */
232         root = of_find_node_by_path("/");
233         if (root) {
234                 perf_level = of_get_property(root,
235                                 "ibm,partition-performance-parameters-level",
236                                              NULL);
237                 if (perf_level && (be32_to_cpup(perf_level) >= 1)) {
238                         seq_printf(m,
239                             "physical_procs_allocated_to_virtualization=%d\n",
240                                    ppp_data.phys_platform_procs);
241                         seq_printf(m, "max_proc_capacity_available=%d\n",
242                                    ppp_data.max_proc_cap_avail);
243                         seq_printf(m, "entitled_proc_capacity_available=%d\n",
244                                    ppp_data.entitled_proc_cap_avail);
245                 }
246
247                 of_node_put(root);
248         }
249 }
250
251 /**
252  * parse_mpp_data
253  * Parse out data returned from h_get_mpp
254  */
255 static void parse_mpp_data(struct seq_file *m)
256 {
257         struct hvcall_mpp_data mpp_data;
258         int rc;
259
260         rc = h_get_mpp(&mpp_data);
261         if (rc)
262                 return;
263
264         seq_printf(m, "entitled_memory=%ld\n", mpp_data.entitled_mem);
265
266         if (mpp_data.mapped_mem != -1)
267                 seq_printf(m, "mapped_entitled_memory=%ld\n",
268                            mpp_data.mapped_mem);
269
270         seq_printf(m, "entitled_memory_group_number=%d\n", mpp_data.group_num);
271         seq_printf(m, "entitled_memory_pool_number=%d\n", mpp_data.pool_num);
272
273         seq_printf(m, "entitled_memory_weight=%d\n", mpp_data.mem_weight);
274         seq_printf(m, "unallocated_entitled_memory_weight=%d\n",
275                    mpp_data.unallocated_mem_weight);
276         seq_printf(m, "unallocated_io_mapping_entitlement=%ld\n",
277                    mpp_data.unallocated_entitlement);
278
279         if (mpp_data.pool_size != -1)
280                 seq_printf(m, "entitled_memory_pool_size=%ld bytes\n",
281                            mpp_data.pool_size);
282
283         seq_printf(m, "entitled_memory_loan_request=%ld\n",
284                    mpp_data.loan_request);
285
286         seq_printf(m, "backing_memory=%ld bytes\n", mpp_data.backing_mem);
287 }
288
289 /**
290  * parse_mpp_x_data
291  * Parse out data returned from h_get_mpp_x
292  */
293 static void parse_mpp_x_data(struct seq_file *m)
294 {
295         struct hvcall_mpp_x_data mpp_x_data;
296
297         if (!firmware_has_feature(FW_FEATURE_XCMO))
298                 return;
299         if (h_get_mpp_x(&mpp_x_data))
300                 return;
301
302         seq_printf(m, "coalesced_bytes=%ld\n", mpp_x_data.coalesced_bytes);
303
304         if (mpp_x_data.pool_coalesced_bytes)
305                 seq_printf(m, "pool_coalesced_bytes=%ld\n",
306                            mpp_x_data.pool_coalesced_bytes);
307         if (mpp_x_data.pool_purr_cycles)
308                 seq_printf(m, "coalesce_pool_purr=%ld\n", mpp_x_data.pool_purr_cycles);
309         if (mpp_x_data.pool_spurr_cycles)
310                 seq_printf(m, "coalesce_pool_spurr=%ld\n", mpp_x_data.pool_spurr_cycles);
311 }
312
313 /*
314  * PAPR defines, in section "7.3.16 System Parameters Option", the token 55 to
315  * read the LPAR name, and the largest output data to 4000 + 2 bytes length.
316  */
317 #define SPLPAR_LPAR_NAME_TOKEN  55
318 #define GET_SYS_PARM_BUF_SIZE   4002
319 #if GET_SYS_PARM_BUF_SIZE > RTAS_DATA_BUF_SIZE
320 #error "GET_SYS_PARM_BUF_SIZE is larger than RTAS_DATA_BUF_SIZE"
321 #endif
322
323 /*
324  * Read the lpar name using the RTAS ibm,get-system-parameter call.
325  *
326  * The name read through this call is updated if changes are made by the end
327  * user on the hypervisor side.
328  *
329  * Some hypervisor (like Qemu) may not provide this value. In that case, a non
330  * null value is returned.
331  */
332 static int read_rtas_lpar_name(struct seq_file *m)
333 {
334         int rc, len, token;
335         union {
336                 char raw_buffer[GET_SYS_PARM_BUF_SIZE];
337                 struct {
338                         __be16 len;
339                         char name[GET_SYS_PARM_BUF_SIZE-2];
340                 };
341         } *local_buffer;
342
343         token = rtas_token("ibm,get-system-parameter");
344         if (token == RTAS_UNKNOWN_SERVICE)
345                 return -EINVAL;
346
347         local_buffer = kmalloc(sizeof(*local_buffer), GFP_KERNEL);
348         if (!local_buffer)
349                 return -ENOMEM;
350
351         do {
352                 spin_lock(&rtas_data_buf_lock);
353                 memset(rtas_data_buf, 0, sizeof(*local_buffer));
354                 rc = rtas_call(token, 3, 1, NULL, SPLPAR_LPAR_NAME_TOKEN,
355                                __pa(rtas_data_buf), sizeof(*local_buffer));
356                 if (!rc)
357                         memcpy(local_buffer->raw_buffer, rtas_data_buf,
358                                sizeof(local_buffer->raw_buffer));
359                 spin_unlock(&rtas_data_buf_lock);
360         } while (rtas_busy_delay(rc));
361
362         if (!rc) {
363                 /* Force end of string */
364                 len = min((int) be16_to_cpu(local_buffer->len),
365                           (int) sizeof(local_buffer->name)-1);
366                 local_buffer->name[len] = '\0';
367
368                 seq_printf(m, "partition_name=%s\n", local_buffer->name);
369         } else
370                 rc = -ENODATA;
371
372         kfree(local_buffer);
373         return rc;
374 }
375
376 /*
377  * Read the LPAR name from the Device Tree.
378  *
379  * The value read in the DT is not updated if the end-user is touching the LPAR
380  * name on the hypervisor side.
381  */
382 static int read_dt_lpar_name(struct seq_file *m)
383 {
384         const char *name;
385
386         if (of_property_read_string(of_root, "ibm,partition-name", &name))
387                 return -ENOENT;
388
389         seq_printf(m, "partition_name=%s\n", name);
390         return 0;
391 }
392
393 static void read_lpar_name(struct seq_file *m)
394 {
395         if (read_rtas_lpar_name(m) && read_dt_lpar_name(m))
396                 pr_err_once("Error can't get the LPAR name");
397 }
398
399 #define SPLPAR_CHARACTERISTICS_TOKEN 20
400 #define SPLPAR_MAXLENGTH 1026*(sizeof(char))
401
402 /*
403  * parse_system_parameter_string()
404  * Retrieve the potential_processors, max_entitled_capacity and friends
405  * through the get-system-parameter rtas call.  Replace keyword strings as
406  * necessary.
407  */
408 static void parse_system_parameter_string(struct seq_file *m)
409 {
410         int call_status;
411
412         unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
413         if (!local_buffer) {
414                 printk(KERN_ERR "%s %s kmalloc failure at line %d\n",
415                        __FILE__, __func__, __LINE__);
416                 return;
417         }
418
419         spin_lock(&rtas_data_buf_lock);
420         memset(rtas_data_buf, 0, SPLPAR_MAXLENGTH);
421         call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
422                                 NULL,
423                                 SPLPAR_CHARACTERISTICS_TOKEN,
424                                 __pa(rtas_data_buf),
425                                 RTAS_DATA_BUF_SIZE);
426         memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
427         local_buffer[SPLPAR_MAXLENGTH - 1] = '\0';
428         spin_unlock(&rtas_data_buf_lock);
429
430         if (call_status != 0) {
431                 printk(KERN_INFO
432                        "%s %s Error calling get-system-parameter (0x%x)\n",
433                        __FILE__, __func__, call_status);
434         } else {
435                 int splpar_strlen;
436                 int idx, w_idx;
437                 char *workbuffer = kzalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
438                 if (!workbuffer) {
439                         printk(KERN_ERR "%s %s kmalloc failure at line %d\n",
440                                __FILE__, __func__, __LINE__);
441                         kfree(local_buffer);
442                         return;
443                 }
444 #ifdef LPARCFG_DEBUG
445                 printk(KERN_INFO "success calling get-system-parameter\n");
446 #endif
447                 splpar_strlen = local_buffer[0] * 256 + local_buffer[1];
448                 local_buffer += 2;      /* step over strlen value */
449
450                 w_idx = 0;
451                 idx = 0;
452                 while ((*local_buffer) && (idx < splpar_strlen)) {
453                         workbuffer[w_idx++] = local_buffer[idx++];
454                         if ((local_buffer[idx] == ',')
455                             || (local_buffer[idx] == '\0')) {
456                                 workbuffer[w_idx] = '\0';
457                                 if (w_idx) {
458                                         /* avoid the empty string */
459                                         seq_printf(m, "%s\n", workbuffer);
460                                 }
461                                 memset(workbuffer, 0, SPLPAR_MAXLENGTH);
462                                 idx++;  /* skip the comma */
463                                 w_idx = 0;
464                         } else if (local_buffer[idx] == '=') {
465                                 /* code here to replace workbuffer contents
466                                    with different keyword strings */
467                                 if (0 == strcmp(workbuffer, "MaxEntCap")) {
468                                         strcpy(workbuffer,
469                                                "partition_max_entitled_capacity");
470                                         w_idx = strlen(workbuffer);
471                                 }
472                                 if (0 == strcmp(workbuffer, "MaxPlatProcs")) {
473                                         strcpy(workbuffer,
474                                                "system_potential_processors");
475                                         w_idx = strlen(workbuffer);
476                                 }
477                         }
478                 }
479                 kfree(workbuffer);
480                 local_buffer -= 2;      /* back up over strlen value */
481         }
482         kfree(local_buffer);
483 }
484
485 /* Return the number of processors in the system.
486  * This function reads through the device tree and counts
487  * the virtual processors, this does not include threads.
488  */
489 static int lparcfg_count_active_processors(void)
490 {
491         struct device_node *cpus_dn;
492         int count = 0;
493
494         for_each_node_by_type(cpus_dn, "cpu") {
495 #ifdef LPARCFG_DEBUG
496                 printk(KERN_ERR "cpus_dn %p\n", cpus_dn);
497 #endif
498                 count++;
499         }
500         return count;
501 }
502
503 static void pseries_cmo_data(struct seq_file *m)
504 {
505         int cpu;
506         unsigned long cmo_faults = 0;
507         unsigned long cmo_fault_time = 0;
508
509         seq_printf(m, "cmo_enabled=%d\n", firmware_has_feature(FW_FEATURE_CMO));
510
511         if (!firmware_has_feature(FW_FEATURE_CMO))
512                 return;
513
514         for_each_possible_cpu(cpu) {
515                 cmo_faults += be64_to_cpu(lppaca_of(cpu).cmo_faults);
516                 cmo_fault_time += be64_to_cpu(lppaca_of(cpu).cmo_fault_time);
517         }
518
519         seq_printf(m, "cmo_faults=%lu\n", cmo_faults);
520         seq_printf(m, "cmo_fault_time_usec=%lu\n",
521                    cmo_fault_time / tb_ticks_per_usec);
522         seq_printf(m, "cmo_primary_psp=%d\n", cmo_get_primary_psp());
523         seq_printf(m, "cmo_secondary_psp=%d\n", cmo_get_secondary_psp());
524         seq_printf(m, "cmo_page_size=%lu\n", cmo_get_page_size());
525 }
526
527 static void splpar_dispatch_data(struct seq_file *m)
528 {
529         int cpu;
530         unsigned long dispatches = 0;
531         unsigned long dispatch_dispersions = 0;
532
533         for_each_possible_cpu(cpu) {
534                 dispatches += be32_to_cpu(lppaca_of(cpu).yield_count);
535                 dispatch_dispersions +=
536                         be32_to_cpu(lppaca_of(cpu).dispersion_count);
537         }
538
539         seq_printf(m, "dispatches=%lu\n", dispatches);
540         seq_printf(m, "dispatch_dispersions=%lu\n", dispatch_dispersions);
541 }
542
543 static void parse_em_data(struct seq_file *m)
544 {
545         unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
546
547         if (firmware_has_feature(FW_FEATURE_LPAR) &&
548             plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
549                 seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]);
550 }
551
552 static void maxmem_data(struct seq_file *m)
553 {
554         unsigned long maxmem = 0;
555
556         maxmem += (unsigned long)drmem_info->n_lmbs * drmem_info->lmb_size;
557         maxmem += hugetlb_total_pages() * PAGE_SIZE;
558
559         seq_printf(m, "MaxMem=%lu\n", maxmem);
560 }
561
562 static int pseries_lparcfg_data(struct seq_file *m, void *v)
563 {
564         int partition_potential_processors;
565         int partition_active_processors;
566         struct device_node *rtas_node;
567         const __be32 *lrdrp = NULL;
568
569         rtas_node = of_find_node_by_path("/rtas");
570         if (rtas_node)
571                 lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL);
572
573         if (lrdrp == NULL) {
574                 partition_potential_processors = vdso_data->processorCount;
575         } else {
576                 partition_potential_processors = be32_to_cpup(lrdrp + 4);
577         }
578         of_node_put(rtas_node);
579
580         partition_active_processors = lparcfg_count_active_processors();
581
582         if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
583                 /* this call handles the ibm,get-system-parameter contents */
584                 read_lpar_name(m);
585                 parse_system_parameter_string(m);
586                 parse_ppp_data(m);
587                 parse_mpp_data(m);
588                 parse_mpp_x_data(m);
589                 pseries_cmo_data(m);
590                 splpar_dispatch_data(m);
591
592                 seq_printf(m, "purr=%ld\n", get_purr());
593                 seq_printf(m, "tbr=%ld\n", mftb());
594         } else {                /* non SPLPAR case */
595
596                 seq_printf(m, "system_active_processors=%d\n",
597                            partition_potential_processors);
598
599                 seq_printf(m, "system_potential_processors=%d\n",
600                            partition_potential_processors);
601
602                 seq_printf(m, "partition_max_entitled_capacity=%d\n",
603                            partition_potential_processors * 100);
604
605                 seq_printf(m, "partition_entitled_capacity=%d\n",
606                            partition_active_processors * 100);
607         }
608
609         show_gpci_data(m);
610
611         seq_printf(m, "partition_active_processors=%d\n",
612                    partition_active_processors);
613
614         seq_printf(m, "partition_potential_processors=%d\n",
615                    partition_potential_processors);
616
617         seq_printf(m, "shared_processor_mode=%d\n",
618                    lppaca_shared_proc(get_lppaca()));
619
620 #ifdef CONFIG_PPC_64S_HASH_MMU
621         if (!radix_enabled())
622                 seq_printf(m, "slb_size=%d\n", mmu_slb_size);
623 #endif
624         parse_em_data(m);
625         maxmem_data(m);
626
627         seq_printf(m, "security_flavor=%u\n", pseries_security_flavor);
628
629         return 0;
630 }
631
632 static ssize_t update_ppp(u64 *entitlement, u8 *weight)
633 {
634         struct hvcall_ppp_data ppp_data;
635         u8 new_weight;
636         u64 new_entitled;
637         ssize_t retval;
638
639         /* Get our current parameters */
640         retval = h_get_ppp(&ppp_data);
641         if (retval)
642                 return retval;
643
644         if (entitlement) {
645                 new_weight = ppp_data.weight;
646                 new_entitled = *entitlement;
647         } else if (weight) {
648                 new_weight = *weight;
649                 new_entitled = ppp_data.entitlement;
650         } else
651                 return -EINVAL;
652
653         pr_debug("%s: current_entitled = %llu, current_weight = %u\n",
654                  __func__, ppp_data.entitlement, ppp_data.weight);
655
656         pr_debug("%s: new_entitled = %llu, new_weight = %u\n",
657                  __func__, new_entitled, new_weight);
658
659         retval = plpar_hcall_norets(H_SET_PPP, new_entitled, new_weight);
660         return retval;
661 }
662
663 /**
664  * update_mpp
665  *
666  * Update the memory entitlement and weight for the partition.  Caller must
667  * specify either a new entitlement or weight, not both, to be updated
668  * since the h_set_mpp call takes both entitlement and weight as parameters.
669  */
670 static ssize_t update_mpp(u64 *entitlement, u8 *weight)
671 {
672         struct hvcall_mpp_data mpp_data;
673         u64 new_entitled;
674         u8 new_weight;
675         ssize_t rc;
676
677         if (entitlement) {
678                 /* Check with vio to ensure the new memory entitlement
679                  * can be handled.
680                  */
681                 rc = vio_cmo_entitlement_update(*entitlement);
682                 if (rc)
683                         return rc;
684         }
685
686         rc = h_get_mpp(&mpp_data);
687         if (rc)
688                 return rc;
689
690         if (entitlement) {
691                 new_weight = mpp_data.mem_weight;
692                 new_entitled = *entitlement;
693         } else if (weight) {
694                 new_weight = *weight;
695                 new_entitled = mpp_data.entitled_mem;
696         } else
697                 return -EINVAL;
698
699         pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
700                  __func__, mpp_data.entitled_mem, mpp_data.mem_weight);
701
702         pr_debug("%s: new_entitled = %llu, new_weight = %u\n",
703                  __func__, new_entitled, new_weight);
704
705         rc = plpar_hcall_norets(H_SET_MPP, new_entitled, new_weight);
706         return rc;
707 }
708
709 /*
710  * Interface for changing system parameters (variable capacity weight
711  * and entitled capacity).  Format of input is "param_name=value";
712  * anything after value is ignored.  Valid parameters at this time are
713  * "partition_entitled_capacity" and "capacity_weight".  We use
714  * H_SET_PPP to alter parameters.
715  *
716  * This function should be invoked only on systems with
717  * FW_FEATURE_SPLPAR.
718  */
719 static ssize_t lparcfg_write(struct file *file, const char __user * buf,
720                              size_t count, loff_t * off)
721 {
722         char kbuf[64];
723         char *tmp;
724         u64 new_entitled, *new_entitled_ptr = &new_entitled;
725         u8 new_weight, *new_weight_ptr = &new_weight;
726         ssize_t retval;
727
728         if (!firmware_has_feature(FW_FEATURE_SPLPAR))
729                 return -EINVAL;
730
731         if (count > sizeof(kbuf))
732                 return -EINVAL;
733
734         if (copy_from_user(kbuf, buf, count))
735                 return -EFAULT;
736
737         kbuf[count - 1] = '\0';
738         tmp = strchr(kbuf, '=');
739         if (!tmp)
740                 return -EINVAL;
741
742         *tmp++ = '\0';
743
744         if (!strcmp(kbuf, "partition_entitled_capacity")) {
745                 char *endp;
746                 *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
747                 if (endp == tmp)
748                         return -EINVAL;
749
750                 retval = update_ppp(new_entitled_ptr, NULL);
751         } else if (!strcmp(kbuf, "capacity_weight")) {
752                 char *endp;
753                 *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
754                 if (endp == tmp)
755                         return -EINVAL;
756
757                 retval = update_ppp(NULL, new_weight_ptr);
758         } else if (!strcmp(kbuf, "entitled_memory")) {
759                 char *endp;
760                 *new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
761                 if (endp == tmp)
762                         return -EINVAL;
763
764                 retval = update_mpp(new_entitled_ptr, NULL);
765         } else if (!strcmp(kbuf, "entitled_memory_weight")) {
766                 char *endp;
767                 *new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
768                 if (endp == tmp)
769                         return -EINVAL;
770
771                 retval = update_mpp(NULL, new_weight_ptr);
772         } else
773                 return -EINVAL;
774
775         if (retval == H_SUCCESS || retval == H_CONSTRAINED) {
776                 retval = count;
777         } else if (retval == H_BUSY) {
778                 retval = -EBUSY;
779         } else if (retval == H_HARDWARE) {
780                 retval = -EIO;
781         } else if (retval == H_PARAMETER) {
782                 retval = -EINVAL;
783         }
784
785         return retval;
786 }
787
788 static int lparcfg_data(struct seq_file *m, void *v)
789 {
790         struct device_node *rootdn;
791         const char *model = "";
792         const char *system_id = "";
793         const char *tmp;
794         const __be32 *lp_index_ptr;
795         unsigned int lp_index = 0;
796
797         seq_printf(m, "%s %s\n", MODULE_NAME, MODULE_VERS);
798
799         rootdn = of_find_node_by_path("/");
800         if (rootdn) {
801                 tmp = of_get_property(rootdn, "model", NULL);
802                 if (tmp)
803                         model = tmp;
804                 tmp = of_get_property(rootdn, "system-id", NULL);
805                 if (tmp)
806                         system_id = tmp;
807                 lp_index_ptr = of_get_property(rootdn, "ibm,partition-no",
808                                         NULL);
809                 if (lp_index_ptr)
810                         lp_index = be32_to_cpup(lp_index_ptr);
811                 of_node_put(rootdn);
812         }
813         seq_printf(m, "serial_number=%s\n", system_id);
814         seq_printf(m, "system_type=%s\n", model);
815         seq_printf(m, "partition_id=%d\n", (int)lp_index);
816
817         return pseries_lparcfg_data(m, v);
818 }
819
820 static int lparcfg_open(struct inode *inode, struct file *file)
821 {
822         return single_open(file, lparcfg_data, NULL);
823 }
824
825 static const struct proc_ops lparcfg_proc_ops = {
826         .proc_read      = seq_read,
827         .proc_write     = lparcfg_write,
828         .proc_open      = lparcfg_open,
829         .proc_release   = single_release,
830         .proc_lseek     = seq_lseek,
831 };
832
833 static int __init lparcfg_init(void)
834 {
835         umode_t mode = 0444;
836
837         /* Allow writing if we have FW_FEATURE_SPLPAR */
838         if (firmware_has_feature(FW_FEATURE_SPLPAR))
839                 mode |= 0200;
840
841         if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_proc_ops)) {
842                 printk(KERN_ERR "Failed to create powerpc/lparcfg\n");
843                 return -EIO;
844         }
845         return 0;
846 }
847 machine_device_initcall(pseries, lparcfg_init);