diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 8b24926..5fc798b 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -34,7 +34,7 @@ struct power_pmu {
 				unsigned long *valp);
 	int		(*get_alternatives)(u64 event_id, unsigned int flags,
 				u64 alt[]);
-	u64             (*bhrb_filter_map)(u64 branch_sample_type);
+	u64             (*bhrb_filter_map)(u64 branch_sample_type, u64 *filter_mask);
 	void            (*config_bhrb)(u64 pmu_bhrb_filter);
 	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
 	int		(*limited_pmc_event)(u64 event_id);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index eeae308..81c4a1d 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -26,6 +26,10 @@
 #define BHRB_PREDICTION		0x0000000000000001
 #define BHRB_EA			0xFFFFFFFFFFFFFFFC
 
+#define for_each_branch_sample_type(x) \
+        for ((x) = PERF_SAMPLE_BRANCH_USER; \
+             (x) < PERF_SAMPLE_BRANCH_MAX; (x) <<= 1)
+
 struct cpu_hw_events {
 	int n_events;
 	int n_percpu;
@@ -47,7 +51,9 @@ struct cpu_hw_events {
 	int n_txn_start;
 
 	/* BHRB bits */
-	u64				bhrb_filter;	/* BHRB HW branch filter */
+	u64				bhrb_hw_filter;	/* BHRB HW branch filter */
+	u64				bhrb_sw_filter; /* BHRB SW branch filter */
+	u64				filter_mask;	/* Branch filter mask */
 	int				bhrb_users;
 	void				*bhrb_context;
 	struct	perf_branch_stack	bhrb_stack;
@@ -400,6 +406,101 @@ static __u64 power_pmu_bhrb_to(u64 addr)
 	return target - (unsigned long)&instr + addr;
 }
 
+#define BRANCH_LINK   0x00000001
+#define BRANCH_LR     0x4C000020
+#define BRANCH_CTR    0x4C000420
+#define BRANCH_TAR    0x4C000460
+
+/* Check the instruction opcodes */
+static bool validate_instruction(unsigned int *addr, u64 bhrb_sw_filter)
+{
+	if (bhrb_sw_filter & PERF_SAMPLE_BRANCH_ANY_RETURN) {
+		/* Link is not set */
+		if (!(*addr & BRANCH_LINK)) {
+			/*
+			 * Conditional and unconditional
+			 * branch to LR.
+			 */
+			if ((*addr & BRANCH_LR) == BRANCH_LR)
+				return true;
+
+			/* Everything else */
+			return false;
+		}
+
+		/* Link is set */
+		return false;
+	}
+
+	if (bhrb_sw_filter & PERF_SAMPLE_BRANCH_IND_CALL) {
+		/* Link is set */
+		if (*addr & BRANCH_LINK) {
+			/*
+			 * Conditional and unconditional
+			 * branch to CTR.
+			 */
+			if ((*addr & BRANCH_CTR) == BRANCH_CTR)
+				return true;
+			/*
+			 * Conditional and unconditional
+			 * branch to LR.
+			 */
+			if ((*addr & BRANCH_LR) == BRANCH_LR)
+				return true;
+			/*
+			 * Conditional and unconditional
+			 * branch to TAR.
+			 */
+			if ((*addr & BRANCH_TAR) == BRANCH_TAR)
+				return true;
+
+			/* Everything else */
+			return false;
+		}
+
+		/* Link is not set */
+		return false;
+	}
+
+	/* No software branch filter, control
+	 * should not have come here.
+	 */
+	return true;
+}
+
+/* Extract the instruction from the address */
+static bool check_instruction(u64 addr, u64 bhrb_sw_filter)
+{
+	unsigned int instr;
+	bool ret;
+
+	if (bhrb_sw_filter == 0)
+		return true;
+
+	if (is_kernel_addr(addr)) {
+		ret = validate_instruction((unsigned int *) addr, bhrb_sw_filter);
+	} else {
+		/*
+		 * Userspace address need to copied first
+		 * before analysis.
+		 */
+		pagefault_disable();
+		ret =  __get_user_inatomic(instr, (unsigned int __user *)addr);
+
+		/*
+		 * If the instruction could not be accessible
+		 * from user space, we still OKAY the entry.
+		 */
+		if (ret) {
+			pagefault_enable();
+			return true;
+		}
+		pagefault_enable();
+		ret = validate_instruction(&instr, bhrb_sw_filter);
+	}
+	return ret;
+}
+
 /* Processing BHRB entries */
 void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
 {
@@ -459,14 +560,28 @@ void power_pmu_bhrb_read(struct cpu_hw_events *cpuhw)
 					addr = 0;
 				}
 				cpuhw->bhrb_entries[u_index].from = addr;
+
+				/* Apply SW filter */
+				if (!check_instruction(cpuhw->
+						bhrb_entries[u_index].from,
+							cpuhw->bhrb_sw_filter))
+					u_index--;
 			} else {
 				/* Branches to immediate field 
 				   (ie I or B form) */
 				cpuhw->bhrb_entries[u_index].from = addr;
-				cpuhw->bhrb_entries[u_index].to =
-					power_pmu_bhrb_to(addr);
-				cpuhw->bhrb_entries[u_index].mispred = pred;
-				cpuhw->bhrb_entries[u_index].predicted = ~pred;
+				if (check_instruction(cpuhw->
+						bhrb_entries[u_index].from,
+						cpuhw->bhrb_sw_filter)) {
+					cpuhw->bhrb_entries[u_index].
+						to = power_pmu_bhrb_to(addr);
+					cpuhw->bhrb_entries[u_index].
+						mispred = pred;
+					cpuhw->bhrb_entries[u_index].
+						predicted = ~pred;
+				} else {
+					u_index--;
+				}
 			}
 			u_index++;
 
@@ -1159,7 +1274,7 @@ static void power_pmu_enable(struct pmu *pmu)
 
  out:
 	if (cpuhw->bhrb_users)
-		ppmu->config_bhrb(cpuhw->bhrb_filter);
+		ppmu->config_bhrb(cpuhw->bhrb_hw_filter);
 
 	local_irq_restore(flags);
 }
@@ -1191,6 +1306,26 @@ static int collect_events(struct perf_event *group, int max_count,
 	return n;
 }
 
+/* SW based branch filters */
+static u64 branch_filter_map(u64 branch_sample_type, u64 *filter_mask)
+{
+	u64 branch_sw_filter = 0;
+
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY) {
+		WARN_ON(*filter_mask != PERF_SAMPLE_BRANCH_ANY);
+		return branch_sw_filter;
+	}
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN) {
+		branch_sw_filter |= PERF_SAMPLE_BRANCH_ANY_RETURN;
+		*filter_mask |= PERF_SAMPLE_BRANCH_ANY_RETURN;
+	}
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL) {
+		branch_sw_filter |= PERF_SAMPLE_BRANCH_IND_CALL;
+		*filter_mask |= PERF_SAMPLE_BRANCH_IND_CALL;
+	}
+	return branch_sw_filter;
+}
+
 /*
  * Add a event to the PMU.
  * If all events are not already frozen, then we disable and
@@ -1254,8 +1389,11 @@ nocheck:
  out:
 	if (has_branch_stack(event)) {
 		power_pmu_bhrb_enable(event);
-		cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
-					event->attr.branch_sample_type);
+
+		cpuhw->bhrb_hw_filter = ppmu->bhrb_filter_map
+			(event->attr.branch_sample_type, &cpuhw->filter_mask);
+	        cpuhw->bhrb_sw_filter = branch_filter_map
+			(event->attr.branch_sample_type, &cpuhw->filter_mask);
 	}
 
 	perf_pmu_enable(event->pmu);
@@ -1531,6 +1669,35 @@ static int hw_perf_cache_event(u64 config, u64 *eventp)
 	return 0;
 }
 
+/* Validate requested filters either in PMU or in SW */
+static int match_filters(u64 branch_sample_type, u64 filter_mask)
+{
+	u64 x;
+
+	if (filter_mask == PERF_SAMPLE_BRANCH_ANY)
+		return true;
+
+	for_each_branch_sample_type(x) {
+		if (!(branch_sample_type & x))
+			continue;
+		/*
+		 * Privilege filter requests have been already
+		 * taken care during base PMU configuration.
+		 */
+		if (x == PERF_SAMPLE_BRANCH_USER)
+			continue;
+		if (x == PERF_SAMPLE_BRANCH_KERNEL)
+			continue;
+		if (x == PERF_SAMPLE_BRANCH_HV)
+			continue;
+
+		/* Requested filter not available */
+		if (!(filter_mask & x))
+			return false;
+	}
+	return true;
+}
+
 static int power_pmu_event_init(struct perf_event *event)
 {
 	u64 ev;
@@ -1637,10 +1804,21 @@ static int power_pmu_event_init(struct perf_event *event)
 	err = power_check_constraints(cpuhw, events, cflags, n + 1);
 
 	if (has_branch_stack(event)) {
-		cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
-					event->attr.branch_sample_type);
+		/* PMU supported branch filters */
+		cpuhw->bhrb_hw_filter = ppmu->bhrb_filter_map
+			(event->attr.branch_sample_type, &cpuhw->filter_mask);
+
+		/* ABI - PMU does not support filter combination */
+		if (cpuhw->bhrb_hw_filter == -1)
+			return -EOPNOTSUPP;
+
+		/* SW supported branch filters */
+		cpuhw->bhrb_sw_filter = branch_filter_map
+			(event->attr.branch_sample_type, &cpuhw->filter_mask);
 
-		if(cpuhw->bhrb_filter == -1)
+		/* ABI - Requested filters are not present */
+		if(!match_filters(event->attr.branch_sample_type,
+							cpuhw->filter_mask))
 			return -EOPNOTSUPP;
 	}
 
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c
index 6e28587..e02027b 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -558,9 +558,10 @@ static int power8_generic_events[] = {
 	[PERF_COUNT_HW_BRANCH_MISSES] =			PM_BR_MPRED_CMPL,
 };
 
-static u64 power8_bhrb_filter_map(u64 branch_sample_type)
+static u64 power8_bhrb_filter_map(u64 branch_sample_type, u64 *filter_mask)
 {
 	u64 pmu_bhrb_filter = 0;
+	*filter_mask = 0;
 
 	/* BHRB and regular PMU events share the same privilege state
 	 * filter configuration. BHRB is always recorded along with a
@@ -570,15 +571,10 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)
 	 */
 
 	/* No branch filter requested */
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
+	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY) {
+		*filter_mask = PERF_SAMPLE_BRANCH_ANY;
 		return pmu_bhrb_filter;
-
-	/* Invalid branch filter options - HW does not support */
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
-		return -1;
-
-	if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL)
-		return -1;
+	}
 
 	/* Invalid branch filter combination - HW does not support */
 	if ((branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) &&
@@ -587,16 +583,17 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type)
 
 	if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
 		pmu_bhrb_filter |= POWER8_MMCRA_IFM1;
+		*filter_mask    |= PERF_SAMPLE_BRANCH_ANY_CALL;
 		return pmu_bhrb_filter;
 	}
 
 	if (branch_sample_type & PERF_SAMPLE_BRANCH_COND) {
 		pmu_bhrb_filter |= POWER8_MMCRA_IFM3;
+		*filter_mask    |= PERF_SAMPLE_BRANCH_COND;
 		return pmu_bhrb_filter;
 	}
 
-	/* Every thing else is unsupported */
-	return -1;
+	return pmu_bhrb_filter;
 }
 
 static void power8_config_bhrb(u64 pmu_bhrb_filter)
