aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/perf
diff options
context:
space:
mode:
authorLi Zhong <zhong@linux.vnet.ibm.com>2015-04-13 03:48:37 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-04-13 23:19:15 -0400
commit7debc970ae7a5573ed43a1dfa242fd1a5390d21a (patch)
tree3bf20766ecf79b8d3e8a41d16bde04bd8f369d6b /arch/powerpc/perf
parentad30cb9946515f72af5c3e89ad9de18870c1a1e7 (diff)
powerpc/perf/hv-24x7: Fail 24x7 initcall if create_events_from_catalog() fails
As Michael pointed out, create_events_from_catalog() fails when we either have: - a kernel bug - some sort of hypervisor misconfiguration - ENOMEM In all the above cases, we can also fail 24x7 initcall. For hypervisor errors, EIO is used so there is something reported in dmesg. Signed-off-by: Li Zhong <zhong@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/perf')
-rw-r--r--arch/powerpc/perf/hv-24x7.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index ead8878ca62b..ff413615a87c 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -647,7 +647,7 @@ static ssize_t catalog_event_len_validate(struct hv_24x7_event_data *event,
647 647
648#define MAX_4K (SIZE_MAX / 4096) 648#define MAX_4K (SIZE_MAX / 4096)
649 649
650static void create_events_from_catalog(struct attribute ***events_, 650static int create_events_from_catalog(struct attribute ***events_,
651 struct attribute ***event_descs_, 651 struct attribute ***event_descs_,
652 struct attribute ***event_long_descs_) 652 struct attribute ***event_long_descs_)
653{ 653{
@@ -665,19 +665,25 @@ static void create_events_from_catalog(struct attribute ***events_,
665 void *event_data, *end; 665 void *event_data, *end;
666 struct hv_24x7_event_data *event; 666 struct hv_24x7_event_data *event;
667 struct rb_root ev_uniq = RB_ROOT; 667 struct rb_root ev_uniq = RB_ROOT;
668 int ret = 0;
668 669
669 if (!page) 670 if (!page) {
671 ret = -ENOMEM;
670 goto e_out; 672 goto e_out;
673 }
671 674
672 hret = h_get_24x7_catalog_page(page, 0, 0); 675 hret = h_get_24x7_catalog_page(page, 0, 0);
673 if (hret) 676 if (hret) {
677 ret = -EIO;
674 goto e_free; 678 goto e_free;
679 }
675 680
676 catalog_version_num = be64_to_cpu(page_0->version); 681 catalog_version_num = be64_to_cpu(page_0->version);
677 catalog_page_len = be32_to_cpu(page_0->length); 682 catalog_page_len = be32_to_cpu(page_0->length);
678 683
679 if (MAX_4K < catalog_page_len) { 684 if (MAX_4K < catalog_page_len) {
680 pr_err("invalid page count: %zu\n", catalog_page_len); 685 pr_err("invalid page count: %zu\n", catalog_page_len);
686 ret = -EIO;
681 goto e_free; 687 goto e_free;
682 } 688 }
683 689
@@ -696,6 +702,7 @@ static void create_events_from_catalog(struct attribute ***events_,
696 || (MAX_4K - event_data_offs < event_data_len)) { 702 || (MAX_4K - event_data_offs < event_data_len)) {
697 pr_err("invalid event data offs %zu and/or len %zu\n", 703 pr_err("invalid event data offs %zu and/or len %zu\n",
698 event_data_offs, event_data_len); 704 event_data_offs, event_data_len);
705 ret = -EIO;
699 goto e_free; 706 goto e_free;
700 } 707 }
701 708
@@ -704,12 +711,14 @@ static void create_events_from_catalog(struct attribute ***events_,
704 event_data_offs, 711 event_data_offs,
705 event_data_offs + event_data_len, 712 event_data_offs + event_data_len,
706 catalog_page_len); 713 catalog_page_len);
714 ret = -EIO;
707 goto e_free; 715 goto e_free;
708 } 716 }
709 717
710 if (SIZE_MAX / MAX_EVENTS_PER_EVENT_DATA - 1 < event_entry_count) { 718 if (SIZE_MAX / MAX_EVENTS_PER_EVENT_DATA - 1 < event_entry_count) {
711 pr_err("event_entry_count %zu is invalid\n", 719 pr_err("event_entry_count %zu is invalid\n",
712 event_entry_count); 720 event_entry_count);
721 ret = -EIO;
713 goto e_free; 722 goto e_free;
714 } 723 }
715 724
@@ -722,6 +731,7 @@ static void create_events_from_catalog(struct attribute ***events_,
722 event_data = vmalloc(event_data_bytes); 731 event_data = vmalloc(event_data_bytes);
723 if (!event_data) { 732 if (!event_data) {
724 pr_err("could not allocate event data\n"); 733 pr_err("could not allocate event data\n");
734 ret = -ENOMEM;
725 goto e_free; 735 goto e_free;
726 } 736 }
727 737
@@ -741,6 +751,7 @@ static void create_events_from_catalog(struct attribute ***events_,
741 if (hret) { 751 if (hret) {
742 pr_err("failed to get event data in page %zu\n", 752 pr_err("failed to get event data in page %zu\n",
743 i + event_data_offs); 753 i + event_data_offs);
754 ret = -EIO;
744 goto e_event_data; 755 goto e_event_data;
745 } 756 }
746 } 757 }
@@ -788,18 +799,24 @@ static void create_events_from_catalog(struct attribute ***events_,
788 event_idx_last, event_entry_count, junk_events); 799 event_idx_last, event_entry_count, junk_events);
789 800
790 events = kmalloc_array(attr_max + 1, sizeof(*events), GFP_KERNEL); 801 events = kmalloc_array(attr_max + 1, sizeof(*events), GFP_KERNEL);
791 if (!events) 802 if (!events) {
803 ret = -ENOMEM;
792 goto e_event_data; 804 goto e_event_data;
805 }
793 806
794 event_descs = kmalloc_array(event_idx + 1, sizeof(*event_descs), 807 event_descs = kmalloc_array(event_idx + 1, sizeof(*event_descs),
795 GFP_KERNEL); 808 GFP_KERNEL);
796 if (!event_descs) 809 if (!event_descs) {
810 ret = -ENOMEM;
797 goto e_event_attrs; 811 goto e_event_attrs;
812 }
798 813
799 event_long_descs = kmalloc_array(event_idx + 1, 814 event_long_descs = kmalloc_array(event_idx + 1,
800 sizeof(*event_long_descs), GFP_KERNEL); 815 sizeof(*event_long_descs), GFP_KERNEL);
801 if (!event_long_descs) 816 if (!event_long_descs) {
817 ret = -ENOMEM;
802 goto e_event_descs; 818 goto e_event_descs;
819 }
803 820
804 /* Iterate over the catalog filling in the attribute vector */ 821 /* Iterate over the catalog filling in the attribute vector */
805 for (junk_events = 0, event_attr_ct = 0, desc_ct = 0, long_desc_ct = 0, 822 for (junk_events = 0, event_attr_ct = 0, desc_ct = 0, long_desc_ct = 0,
@@ -853,7 +870,7 @@ static void create_events_from_catalog(struct attribute ***events_,
853 *events_ = events; 870 *events_ = events;
854 *event_descs_ = event_descs; 871 *event_descs_ = event_descs;
855 *event_long_descs_ = event_long_descs; 872 *event_long_descs_ = event_long_descs;
856 return; 873 return 0;
857 874
858e_event_descs: 875e_event_descs:
859 kfree(event_descs); 876 kfree(event_descs);
@@ -867,6 +884,7 @@ e_out:
867 *events_ = NULL; 884 *events_ = NULL;
868 *event_descs_ = NULL; 885 *event_descs_ = NULL;
869 *event_long_descs_ = NULL; 886 *event_long_descs_ = NULL;
887 return ret;
870} 888}
871 889
872static ssize_t catalog_read(struct file *filp, struct kobject *kobj, 890static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
@@ -1275,10 +1293,13 @@ static int hv_24x7_init(void)
1275 /* sampling not supported */ 1293 /* sampling not supported */
1276 h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; 1294 h_24x7_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
1277 1295
1278 create_events_from_catalog(&event_group.attrs, 1296 r = create_events_from_catalog(&event_group.attrs,
1279 &event_desc_group.attrs, 1297 &event_desc_group.attrs,
1280 &event_long_desc_group.attrs); 1298 &event_long_desc_group.attrs);
1281 1299
1300 if (r)
1301 return r;
1302
1282 r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1); 1303 r = perf_pmu_register(&h_24x7_pmu, h_24x7_pmu.name, -1);
1283 if (r) 1304 if (r)
1284 return r; 1305 return r;