|
17 | 17 |
|
18 | 18 | #include <linux/cpu.h> |
19 | 19 | #include <linux/kernfs.h> |
| 20 | +#include <linux/math.h> |
20 | 21 | #include <linux/seq_file.h> |
21 | 22 | #include <linux/slab.h> |
22 | 23 | #include <linux/tick.h> |
@@ -601,6 +602,77 @@ void mon_event_read(struct rmid_read *rr, struct rdt_resource *r, |
601 | 602 | resctrl_arch_mon_ctx_free(r, evt->evtid, rr->arch_mon_ctx); |
602 | 603 | } |
603 | 604 |
|
| 605 | +/* |
| 606 | + * Decimal place precision to use for each number of fixed-point |
| 607 | + * binary bits computed from ceil(binary_bits * log10(2)) except |
| 608 | + * binary_bits == 0 which will print "value.0" |
| 609 | + */ |
| 610 | +static const unsigned int decplaces[MAX_BINARY_BITS + 1] = { |
| 611 | + [0] = 1, |
| 612 | + [1] = 1, |
| 613 | + [2] = 1, |
| 614 | + [3] = 1, |
| 615 | + [4] = 2, |
| 616 | + [5] = 2, |
| 617 | + [6] = 2, |
| 618 | + [7] = 3, |
| 619 | + [8] = 3, |
| 620 | + [9] = 3, |
| 621 | + [10] = 4, |
| 622 | + [11] = 4, |
| 623 | + [12] = 4, |
| 624 | + [13] = 4, |
| 625 | + [14] = 5, |
| 626 | + [15] = 5, |
| 627 | + [16] = 5, |
| 628 | + [17] = 6, |
| 629 | + [18] = 6, |
| 630 | + [19] = 6, |
| 631 | + [20] = 7, |
| 632 | + [21] = 7, |
| 633 | + [22] = 7, |
| 634 | + [23] = 7, |
| 635 | + [24] = 8, |
| 636 | + [25] = 8, |
| 637 | + [26] = 8, |
| 638 | + [27] = 9 |
| 639 | +}; |
| 640 | + |
| 641 | +static void print_event_value(struct seq_file *m, unsigned int binary_bits, u64 val) |
| 642 | +{ |
| 643 | + unsigned long long frac = 0; |
| 644 | + |
| 645 | + if (binary_bits) { |
| 646 | + /* Mask off the integer part of the fixed-point value. */ |
| 647 | + frac = val & GENMASK_ULL(binary_bits - 1, 0); |
| 648 | + |
| 649 | + /* |
| 650 | + * Multiply by 10^{desired decimal places}. The integer part of |
| 651 | + * the fixed point value is now almost what is needed. |
| 652 | + */ |
| 653 | + frac *= int_pow(10ull, decplaces[binary_bits]); |
| 654 | + |
| 655 | + /* |
| 656 | + * Round to nearest by adding a value that would be a "1" in the |
| 657 | + * binary_bits + 1 place. Integer part of fixed point value is |
| 658 | + * now the needed value. |
| 659 | + */ |
| 660 | + frac += 1ull << (binary_bits - 1); |
| 661 | + |
| 662 | + /* |
| 663 | + * Extract the integer part of the value. This is the decimal |
| 664 | + * representation of the original fixed-point fractional value. |
| 665 | + */ |
| 666 | + frac >>= binary_bits; |
| 667 | + } |
| 668 | + |
| 669 | + /* |
| 670 | + * "frac" is now in the range [0 .. 10^decplaces). I.e. string |
| 671 | + * representation will fit into chosen number of decimal places. |
| 672 | + */ |
| 673 | + seq_printf(m, "%llu.%0*llu\n", val >> binary_bits, decplaces[binary_bits], frac); |
| 674 | +} |
| 675 | + |
604 | 676 | int rdtgroup_mondata_show(struct seq_file *m, void *arg) |
605 | 677 | { |
606 | 678 | struct kernfs_open_file *of = m->private; |
@@ -678,6 +750,8 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg) |
678 | 750 | seq_puts(m, "Unavailable\n"); |
679 | 751 | else if (rr.err == -ENOENT) |
680 | 752 | seq_puts(m, "Unassigned\n"); |
| 753 | + else if (evt->is_floating_point) |
| 754 | + print_event_value(m, evt->binary_bits, rr.val); |
681 | 755 | else |
682 | 756 | seq_printf(m, "%llu\n", rr.val); |
683 | 757 |
|
|
0 commit comments