linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] perf/core: Address filter fixes / changes
@ 2022-01-31  7:24 Adrian Hunter
  2022-01-31  7:24 ` [PATCH 1/5] perf/x86/intel/pt: Relax address filter validation Adrian Hunter
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Adrian Hunter @ 2022-01-31  7:24 UTC (permalink / raw)
  To: Peter Zijlstra, Alexander Shishkin
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	kvm, H Peter Anvin, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Mathieu Poirier, Suzuki K Poulose, Leo Yan

Hi

Here are some Address Filter fixes and changes, primarily for Intel PT, but
Coresight could be affected also by "perf/core: Allow kernel address filter
when not filtering the kernel".

A resulting tidy-up ("x86: Share definition of __is_canonical_address()")
touches a few otherwise unrelated files in mm and kvm, but there are no
functional changes there.


Adrian Hunter (5):
      perf/x86/intel/pt: Relax address filter validation
      x86: Share definition of __is_canonical_address()
      perf/core: Fix address filter parser for multiple filters
      perf/x86/intel/pt: Fix address filter config for 32-bit kernel
      perf/core: Allow kernel address filter when not filtering the kernel

 arch/x86/events/intel/pt.c  | 55 +++++++++++++++++++++++++++++++++------------
 arch/x86/include/asm/page.h | 10 +++++++++
 arch/x86/kvm/emulate.c      |  4 ++--
 arch/x86/kvm/x86.c          |  2 +-
 arch/x86/kvm/x86.h          |  7 +-----
 arch/x86/mm/maccess.c       |  7 +-----
 kernel/events/core.c        |  5 +++--
 7 files changed, 59 insertions(+), 31 deletions(-)


Regards
Adrian

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/5] perf/x86/intel/pt: Relax address filter validation
  2022-01-31  7:24 [PATCH 0/5] perf/core: Address filter fixes / changes Adrian Hunter
@ 2022-01-31  7:24 ` Adrian Hunter
  2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
  2022-01-31  7:24 ` [PATCH 2/5] x86: Share definition of __is_canonical_address() Adrian Hunter
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2022-01-31  7:24 UTC (permalink / raw)
  To: Peter Zijlstra, Alexander Shishkin
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	kvm, H Peter Anvin, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Mathieu Poirier, Suzuki K Poulose, Leo Yan

The requirement for 64-bit address filters is that they are canonical
addresses. In other respects any address range is allowed which would
include user space addresses.

That can be useful for tracing virtual machine guests because address
filtering can be used to advantage in place of current privilege level
(CPL) filtering.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 arch/x86/events/intel/pt.c | 63 ++++++++++++++++++++++++++++++--------
 1 file changed, 50 insertions(+), 13 deletions(-)

diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index ae396fdfabab..4443de56a2d5 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -13,6 +13,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/types.h>
+#include <linux/bits.h>
+#include <linux/limits.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 
@@ -1363,11 +1365,37 @@ static void pt_addr_filters_fini(struct perf_event *event)
 	event->hw.addr_filters = NULL;
 }
 
-static inline bool valid_kernel_ip(unsigned long ip)
+#ifdef CONFIG_X86_64
+static u64 canonical_address(u64 vaddr, u8 vaddr_bits)
 {
-	return virt_addr_valid(ip) && kernel_ip(ip);
+	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
 }
 
+static u64 is_canonical_address(u64 vaddr, u8 vaddr_bits)
+{
+	return canonical_address(vaddr, vaddr_bits) == vaddr;
+}
+
+/* Clamp to a canonical address greater-than-or-equal-to the address given */
+static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
+{
+	return is_canonical_address(vaddr, vaddr_bits) ?
+	       vaddr :
+	       -BIT_ULL(vaddr_bits - 1);
+}
+
+/* Clamp to a canonical address less-than-or-equal-to the address given */
+static u64 clamp_to_le_canonical_addr(u64 vaddr, u8 vaddr_bits)
+{
+	return is_canonical_address(vaddr, vaddr_bits) ?
+	       vaddr :
+	       BIT_ULL(vaddr_bits - 1) - 1;
+}
+#else
+#define clamp_to_ge_canonical_addr(x, y) (x)
+#define clamp_to_le_canonical_addr(x, y) (x)
+#endif
+
 static int pt_event_addr_filters_validate(struct list_head *filters)
 {
 	struct perf_addr_filter *filter;
@@ -1382,14 +1410,6 @@ static int pt_event_addr_filters_validate(struct list_head *filters)
 		    filter->action == PERF_ADDR_FILTER_ACTION_START)
 			return -EOPNOTSUPP;
 
-		if (!filter->path.dentry) {
-			if (!valid_kernel_ip(filter->offset))
-				return -EINVAL;
-
-			if (!valid_kernel_ip(filter->offset + filter->size))
-				return -EINVAL;
-		}
-
 		if (++range > intel_pt_validate_hw_cap(PT_CAP_num_address_ranges))
 			return -EOPNOTSUPP;
 	}
@@ -1413,9 +1433,26 @@ static void pt_event_addr_filters_sync(struct perf_event *event)
 		if (filter->path.dentry && !fr[range].start) {
 			msr_a = msr_b = 0;
 		} else {
-			/* apply the offset */
-			msr_a = fr[range].start;
-			msr_b = msr_a + fr[range].size - 1;
+			unsigned long n = fr[range].size - 1;
+			unsigned long a = fr[range].start;
+			unsigned long b;
+
+			if (a > ULONG_MAX - n)
+				b = ULONG_MAX;
+			else
+				b = a + n;
+			/*
+			 * Apply the offset. 64-bit addresses written to the
+			 * MSRs must be canonical, but the range can encompass
+			 * non-canonical addresses. Since software cannot
+			 * execute at non-canonical addresses, adjusting to
+			 * canonical addresses does not affect the result of the
+			 * address filter.
+			 */
+			msr_a = clamp_to_ge_canonical_addr(a, boot_cpu_data.x86_virt_bits);
+			msr_b = clamp_to_le_canonical_addr(b, boot_cpu_data.x86_virt_bits);
+			if (msr_b < msr_a)
+				msr_a = msr_b = 0;
 		}
 
 		filters->filter[range].msr_a  = msr_a;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] x86: Share definition of __is_canonical_address()
  2022-01-31  7:24 [PATCH 0/5] perf/core: Address filter fixes / changes Adrian Hunter
  2022-01-31  7:24 ` [PATCH 1/5] perf/x86/intel/pt: Relax address filter validation Adrian Hunter
@ 2022-01-31  7:24 ` Adrian Hunter
  2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
  2022-01-31  7:24 ` [PATCH 3/5] perf/core: Fix address filter parser for multiple filters Adrian Hunter
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2022-01-31  7:24 UTC (permalink / raw)
  To: Peter Zijlstra, Alexander Shishkin
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	kvm, H Peter Anvin, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Mathieu Poirier, Suzuki K Poulose, Leo Yan

Reduce code duplication by moving canonical address code to a common header
file.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 arch/x86/events/intel/pt.c  | 14 ++------------
 arch/x86/include/asm/page.h | 10 ++++++++++
 arch/x86/kvm/emulate.c      |  4 ++--
 arch/x86/kvm/x86.c          |  2 +-
 arch/x86/kvm/x86.h          |  7 +------
 arch/x86/mm/maccess.c       |  7 +------
 6 files changed, 17 insertions(+), 27 deletions(-)

diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 4443de56a2d5..4015c1364463 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -1366,20 +1366,10 @@ static void pt_addr_filters_fini(struct perf_event *event)
 }
 
 #ifdef CONFIG_X86_64
-static u64 canonical_address(u64 vaddr, u8 vaddr_bits)
-{
-	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
-}
-
-static u64 is_canonical_address(u64 vaddr, u8 vaddr_bits)
-{
-	return canonical_address(vaddr, vaddr_bits) == vaddr;
-}
-
 /* Clamp to a canonical address greater-than-or-equal-to the address given */
 static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
 {
-	return is_canonical_address(vaddr, vaddr_bits) ?
+	return __is_canonical_address(vaddr, vaddr_bits) ?
 	       vaddr :
 	       -BIT_ULL(vaddr_bits - 1);
 }
@@ -1387,7 +1377,7 @@ static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
 /* Clamp to a canonical address less-than-or-equal-to the address given */
 static u64 clamp_to_le_canonical_addr(u64 vaddr, u8 vaddr_bits)
 {
-	return is_canonical_address(vaddr, vaddr_bits) ?
+	return __is_canonical_address(vaddr, vaddr_bits) ?
 	       vaddr :
 	       BIT_ULL(vaddr_bits - 1) - 1;
 }
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 4d5810c8fab7..9cc82f305f4b 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -71,6 +71,16 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
 extern bool __virt_addr_valid(unsigned long kaddr);
 #define virt_addr_valid(kaddr)	__virt_addr_valid((unsigned long) (kaddr))
 
+static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
+{
+	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
+}
+
+static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits)
+{
+	return __canonical_address(vaddr, vaddr_bits) == vaddr;
+}
+
 #endif	/* __ASSEMBLY__ */
 
 #include <asm-generic/memory_model.h>
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 5719d8cfdbd9..40da8c7f3019 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -665,7 +665,7 @@ static inline u8 ctxt_virt_addr_bits(struct x86_emulate_ctxt *ctxt)
 static inline bool emul_is_noncanonical_address(u64 la,
 						struct x86_emulate_ctxt *ctxt)
 {
-	return get_canonical(la, ctxt_virt_addr_bits(ctxt)) != la;
+	return !__is_canonical_address(la, ctxt_virt_addr_bits(ctxt));
 }
 
 /*
@@ -715,7 +715,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
 	case X86EMUL_MODE_PROT64:
 		*linear = la;
 		va_bits = ctxt_virt_addr_bits(ctxt);
-		if (get_canonical(la, va_bits) != la)
+		if (!__is_canonical_address(la, va_bits))
 			goto bad;
 
 		*max_size = min_t(u64, ~0u, (1ull << va_bits) - la);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 9e43d756312f..af15a7065aa7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1735,7 +1735,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
 		 * value, and that something deterministic happens if the guest
 		 * invokes 64-bit SYSENTER.
 		 */
-		data = get_canonical(data, vcpu_virt_addr_bits(vcpu));
+		data = __canonical_address(data, vcpu_virt_addr_bits(vcpu));
 		break;
 	case MSR_TSC_AUX:
 		if (!kvm_is_supported_user_return_msr(MSR_TSC_AUX))
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 635b75f9e145..fc4b68ab8d71 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -211,14 +211,9 @@ static inline u8 vcpu_virt_addr_bits(struct kvm_vcpu *vcpu)
 	return kvm_read_cr4_bits(vcpu, X86_CR4_LA57) ? 57 : 48;
 }
 
-static inline u64 get_canonical(u64 la, u8 vaddr_bits)
-{
-	return ((int64_t)la << (64 - vaddr_bits)) >> (64 - vaddr_bits);
-}
-
 static inline bool is_noncanonical_address(u64 la, struct kvm_vcpu *vcpu)
 {
-	return get_canonical(la, vcpu_virt_addr_bits(vcpu)) != la;
+	return !__is_canonical_address(la, vcpu_virt_addr_bits(vcpu));
 }
 
 static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/mm/maccess.c b/arch/x86/mm/maccess.c
index 92ec176a7293..5a53c2cc169c 100644
--- a/arch/x86/mm/maccess.c
+++ b/arch/x86/mm/maccess.c
@@ -4,11 +4,6 @@
 #include <linux/kernel.h>
 
 #ifdef CONFIG_X86_64
-static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
-{
-	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
-}
-
 bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
 	unsigned long vaddr = (unsigned long)unsafe_src;
@@ -19,7 +14,7 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 	 * we also need to include the userspace guard page.
 	 */
 	return vaddr >= TASK_SIZE_MAX + PAGE_SIZE &&
-	       canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
+	       __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
 }
 #else
 bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] perf/core: Fix address filter parser for multiple filters
  2022-01-31  7:24 [PATCH 0/5] perf/core: Address filter fixes / changes Adrian Hunter
  2022-01-31  7:24 ` [PATCH 1/5] perf/x86/intel/pt: Relax address filter validation Adrian Hunter
  2022-01-31  7:24 ` [PATCH 2/5] x86: Share definition of __is_canonical_address() Adrian Hunter
@ 2022-01-31  7:24 ` Adrian Hunter
  2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
  2022-01-31  7:24 ` [PATCH 4/5] perf/x86/intel/pt: Fix address filter config for 32-bit kernel Adrian Hunter
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2022-01-31  7:24 UTC (permalink / raw)
  To: Peter Zijlstra, Alexander Shishkin
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	kvm, H Peter Anvin, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Mathieu Poirier, Suzuki K Poulose, Leo Yan

Reset appropriate variables in the parser loop between parsing separate
filters, so that they do not interfere with parsing the next filter.

Fixes: 375637bc524952 ("perf/core: Introduce address range filtering")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index fc18664f49b0..af043a1a06ca 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -10497,8 +10497,11 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
 			}
 
 			/* ready to consume more filters */
+			kfree(filename);
+			filename = NULL;
 			state = IF_STATE_ACTION;
 			filter = NULL;
+			kernel = 0;
 		}
 	}
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] perf/x86/intel/pt: Fix address filter config for 32-bit kernel
  2022-01-31  7:24 [PATCH 0/5] perf/core: Address filter fixes / changes Adrian Hunter
                   ` (2 preceding siblings ...)
  2022-01-31  7:24 ` [PATCH 3/5] perf/core: Fix address filter parser for multiple filters Adrian Hunter
@ 2022-01-31  7:24 ` Adrian Hunter
  2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
  2022-01-31  7:24 ` [PATCH 5/5] perf/core: Allow kernel address filter when not filtering the kernel Adrian Hunter
  2022-02-01 13:25 ` [PATCH 0/5] perf/core: Address filter fixes / changes Peter Zijlstra
  5 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2022-01-31  7:24 UTC (permalink / raw)
  To: Peter Zijlstra, Alexander Shishkin
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	kvm, H Peter Anvin, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Mathieu Poirier, Suzuki K Poulose, Leo Yan

Change from shifting 'unsigned long' to 'u64' to prevent the config bits
being lost on a 32-bit kernel.

Fixes: eadf48cab4b6b0 ("perf/x86/intel/pt: Add support for address range filtering in PT")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 arch/x86/events/intel/pt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 4015c1364463..aa66c0c7b18b 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -490,7 +490,7 @@ static u64 pt_config_filters(struct perf_event *event)
 			pt->filters.filter[range].msr_b = filter->msr_b;
 		}
 
-		rtit_ctl |= filter->config << pt_address_ranges[range].reg_off;
+		rtit_ctl |= (u64)filter->config << pt_address_ranges[range].reg_off;
 	}
 
 	return rtit_ctl;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] perf/core: Allow kernel address filter when not filtering the kernel
  2022-01-31  7:24 [PATCH 0/5] perf/core: Address filter fixes / changes Adrian Hunter
                   ` (3 preceding siblings ...)
  2022-01-31  7:24 ` [PATCH 4/5] perf/x86/intel/pt: Fix address filter config for 32-bit kernel Adrian Hunter
@ 2022-01-31  7:24 ` Adrian Hunter
  2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
  2022-02-01 13:25 ` [PATCH 0/5] perf/core: Address filter fixes / changes Peter Zijlstra
  5 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2022-01-31  7:24 UTC (permalink / raw)
  To: Peter Zijlstra, Alexander Shishkin
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, linux-kernel,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	kvm, H Peter Anvin, Paolo Bonzini, Sean Christopherson,
	Vitaly Kuznetsov, Mathieu Poirier, Suzuki K Poulose, Leo Yan

The so-called 'kernel' address filter can also be useful for filtering
fixed addresses in user space.  Allow that.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 kernel/events/core.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index af043a1a06ca..7670b0918e46 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -10454,8 +10454,6 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
 		 */
 		if (state == IF_STATE_END) {
 			ret = -EINVAL;
-			if (kernel && event->attr.exclude_kernel)
-				goto fail;
 
 			/*
 			 * ACTION "filter" must have a non-zero length region
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/5] perf/core: Address filter fixes / changes
  2022-01-31  7:24 [PATCH 0/5] perf/core: Address filter fixes / changes Adrian Hunter
                   ` (4 preceding siblings ...)
  2022-01-31  7:24 ` [PATCH 5/5] perf/core: Allow kernel address filter when not filtering the kernel Adrian Hunter
@ 2022-02-01 13:25 ` Peter Zijlstra
  5 siblings, 0 replies; 12+ messages in thread
From: Peter Zijlstra @ 2022-02-01 13:25 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Alexander Shishkin, Arnaldo Carvalho de Melo, Jiri Olsa,
	linux-kernel, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, kvm, H Peter Anvin, Paolo Bonzini,
	Sean Christopherson, Vitaly Kuznetsov, Mathieu Poirier,
	Suzuki K Poulose, Leo Yan

On Mon, Jan 31, 2022 at 09:24:48AM +0200, Adrian Hunter wrote:
> Adrian Hunter (5):
>       perf/x86/intel/pt: Relax address filter validation
>       x86: Share definition of __is_canonical_address()
>       perf/core: Fix address filter parser for multiple filters
>       perf/x86/intel/pt: Fix address filter config for 32-bit kernel
>       perf/core: Allow kernel address filter when not filtering the kernel
> 
>  arch/x86/events/intel/pt.c  | 55 +++++++++++++++++++++++++++++++++------------
>  arch/x86/include/asm/page.h | 10 +++++++++
>  arch/x86/kvm/emulate.c      |  4 ++--
>  arch/x86/kvm/x86.c          |  2 +-
>  arch/x86/kvm/x86.h          |  7 +-----
>  arch/x86/mm/maccess.c       |  7 +-----
>  kernel/events/core.c        |  5 +++--
>  7 files changed, 59 insertions(+), 31 deletions(-)

Thanks! queued then for perf/core, if they're urgent give a shout and
I'll see if I can stick them in perf/urgent instead.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [tip: perf/core] perf/core: Allow kernel address filter when not filtering the kernel
  2022-01-31  7:24 ` [PATCH 5/5] perf/core: Allow kernel address filter when not filtering the kernel Adrian Hunter
@ 2022-02-03 14:33   ` tip-bot2 for Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for Adrian Hunter @ 2022-02-03 14:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Adrian Hunter, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     58b2ff2c18b1e1d7232b8007a5698ec4ee7a7a0d
Gitweb:        https://git.kernel.org/tip/58b2ff2c18b1e1d7232b8007a5698ec4ee7a7a0d
Author:        Adrian Hunter <adrian.hunter@intel.com>
AuthorDate:    Mon, 31 Jan 2022 09:24:53 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 02 Feb 2022 13:11:43 +01:00

perf/core: Allow kernel address filter when not filtering the kernel

The so-called 'kernel' address filter can also be useful for filtering
fixed addresses in user space.  Allow that.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220131072453.2839535-6-adrian.hunter@intel.com
---
 kernel/events/core.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2889b82..afbf388 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -10515,8 +10515,6 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
 		 */
 		if (state == IF_STATE_END) {
 			ret = -EINVAL;
-			if (kernel && event->attr.exclude_kernel)
-				goto fail;
 
 			/*
 			 * ACTION "filter" must have a non-zero length region

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [tip: perf/core] perf/x86/intel/pt: Fix address filter config for 32-bit kernel
  2022-01-31  7:24 ` [PATCH 4/5] perf/x86/intel/pt: Fix address filter config for 32-bit kernel Adrian Hunter
@ 2022-02-03 14:33   ` tip-bot2 for Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for Adrian Hunter @ 2022-02-03 14:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Adrian Hunter, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     e5524bf1047eb3b3f3f33b5f59897ba67b3ade87
Gitweb:        https://git.kernel.org/tip/e5524bf1047eb3b3f3f33b5f59897ba67b3ade87
Author:        Adrian Hunter <adrian.hunter@intel.com>
AuthorDate:    Mon, 31 Jan 2022 09:24:52 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 02 Feb 2022 13:11:43 +01:00

perf/x86/intel/pt: Fix address filter config for 32-bit kernel

Change from shifting 'unsigned long' to 'u64' to prevent the config bits
being lost on a 32-bit kernel.

Fixes: eadf48cab4b6b0 ("perf/x86/intel/pt: Add support for address range filtering in PT")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220131072453.2839535-5-adrian.hunter@intel.com
---
 arch/x86/events/intel/pt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 93676a5..f061dc2 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -474,7 +474,7 @@ static u64 pt_config_filters(struct perf_event *event)
 			pt->filters.filter[range].msr_b = filter->msr_b;
 		}
 
-		rtit_ctl |= filter->config << pt_address_ranges[range].reg_off;
+		rtit_ctl |= (u64)filter->config << pt_address_ranges[range].reg_off;
 	}
 
 	return rtit_ctl;

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [tip: perf/core] perf/core: Fix address filter parser for multiple filters
  2022-01-31  7:24 ` [PATCH 3/5] perf/core: Fix address filter parser for multiple filters Adrian Hunter
@ 2022-02-03 14:33   ` tip-bot2 for Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for Adrian Hunter @ 2022-02-03 14:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Adrian Hunter, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     d680ff24e9e14444c63945b43a37ede7cd6958f9
Gitweb:        https://git.kernel.org/tip/d680ff24e9e14444c63945b43a37ede7cd6958f9
Author:        Adrian Hunter <adrian.hunter@intel.com>
AuthorDate:    Mon, 31 Jan 2022 09:24:51 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 02 Feb 2022 13:11:42 +01:00

perf/core: Fix address filter parser for multiple filters

Reset appropriate variables in the parser loop between parsing separate
filters, so that they do not interfere with parsing the next filter.

Fixes: 375637bc524952 ("perf/core: Introduce address range filtering")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220131072453.2839535-4-adrian.hunter@intel.com
---
 kernel/events/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 76c754e..2889b82 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -10558,8 +10558,11 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
 			}
 
 			/* ready to consume more filters */
+			kfree(filename);
+			filename = NULL;
 			state = IF_STATE_ACTION;
 			filter = NULL;
+			kernel = 0;
 		}
 	}
 

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [tip: perf/core] x86: Share definition of __is_canonical_address()
  2022-01-31  7:24 ` [PATCH 2/5] x86: Share definition of __is_canonical_address() Adrian Hunter
@ 2022-02-03 14:33   ` tip-bot2 for Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for Adrian Hunter @ 2022-02-03 14:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Adrian Hunter, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     1fb85d06ad6754796cd1b920639ca9d8840abefd
Gitweb:        https://git.kernel.org/tip/1fb85d06ad6754796cd1b920639ca9d8840abefd
Author:        Adrian Hunter <adrian.hunter@intel.com>
AuthorDate:    Mon, 31 Jan 2022 09:24:50 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 02 Feb 2022 13:11:42 +01:00

x86: Share definition of __is_canonical_address()

Reduce code duplication by moving canonical address code to a common header
file.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220131072453.2839535-3-adrian.hunter@intel.com
---
 arch/x86/events/intel/pt.c  | 14 ++------------
 arch/x86/include/asm/page.h | 10 ++++++++++
 arch/x86/kvm/emulate.c      |  4 ++--
 arch/x86/kvm/x86.c          |  2 +-
 arch/x86/kvm/x86.h          |  7 +------
 arch/x86/mm/maccess.c       |  7 +------
 6 files changed, 17 insertions(+), 27 deletions(-)

diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 0ebcf9a..93676a5 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -1350,20 +1350,10 @@ static void pt_addr_filters_fini(struct perf_event *event)
 }
 
 #ifdef CONFIG_X86_64
-static u64 canonical_address(u64 vaddr, u8 vaddr_bits)
-{
-	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
-}
-
-static u64 is_canonical_address(u64 vaddr, u8 vaddr_bits)
-{
-	return canonical_address(vaddr, vaddr_bits) == vaddr;
-}
-
 /* Clamp to a canonical address greater-than-or-equal-to the address given */
 static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
 {
-	return is_canonical_address(vaddr, vaddr_bits) ?
+	return __is_canonical_address(vaddr, vaddr_bits) ?
 	       vaddr :
 	       -BIT_ULL(vaddr_bits - 1);
 }
@@ -1371,7 +1361,7 @@ static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
 /* Clamp to a canonical address less-than-or-equal-to the address given */
 static u64 clamp_to_le_canonical_addr(u64 vaddr, u8 vaddr_bits)
 {
-	return is_canonical_address(vaddr, vaddr_bits) ?
+	return __is_canonical_address(vaddr, vaddr_bits) ?
 	       vaddr :
 	       BIT_ULL(vaddr_bits - 1) - 1;
 }
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 4d5810c..9cc82f3 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -71,6 +71,16 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
 extern bool __virt_addr_valid(unsigned long kaddr);
 #define virt_addr_valid(kaddr)	__virt_addr_valid((unsigned long) (kaddr))
 
+static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
+{
+	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
+}
+
+static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits)
+{
+	return __canonical_address(vaddr, vaddr_bits) == vaddr;
+}
+
 #endif	/* __ASSEMBLY__ */
 
 #include <asm-generic/memory_model.h>
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 5719d8c..40da8c7 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -665,7 +665,7 @@ static inline u8 ctxt_virt_addr_bits(struct x86_emulate_ctxt *ctxt)
 static inline bool emul_is_noncanonical_address(u64 la,
 						struct x86_emulate_ctxt *ctxt)
 {
-	return get_canonical(la, ctxt_virt_addr_bits(ctxt)) != la;
+	return !__is_canonical_address(la, ctxt_virt_addr_bits(ctxt));
 }
 
 /*
@@ -715,7 +715,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
 	case X86EMUL_MODE_PROT64:
 		*linear = la;
 		va_bits = ctxt_virt_addr_bits(ctxt);
-		if (get_canonical(la, va_bits) != la)
+		if (!__is_canonical_address(la, va_bits))
 			goto bad;
 
 		*max_size = min_t(u64, ~0u, (1ull << va_bits) - la);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 74b53a1..197209f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1735,7 +1735,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
 		 * value, and that something deterministic happens if the guest
 		 * invokes 64-bit SYSENTER.
 		 */
-		data = get_canonical(data, vcpu_virt_addr_bits(vcpu));
+		data = __canonical_address(data, vcpu_virt_addr_bits(vcpu));
 		break;
 	case MSR_TSC_AUX:
 		if (!kvm_is_supported_user_return_msr(MSR_TSC_AUX))
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 635b75f..fc4b68a 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -211,14 +211,9 @@ static inline u8 vcpu_virt_addr_bits(struct kvm_vcpu *vcpu)
 	return kvm_read_cr4_bits(vcpu, X86_CR4_LA57) ? 57 : 48;
 }
 
-static inline u64 get_canonical(u64 la, u8 vaddr_bits)
-{
-	return ((int64_t)la << (64 - vaddr_bits)) >> (64 - vaddr_bits);
-}
-
 static inline bool is_noncanonical_address(u64 la, struct kvm_vcpu *vcpu)
 {
-	return get_canonical(la, vcpu_virt_addr_bits(vcpu)) != la;
+	return !__is_canonical_address(la, vcpu_virt_addr_bits(vcpu));
 }
 
 static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
diff --git a/arch/x86/mm/maccess.c b/arch/x86/mm/maccess.c
index 92ec176..5a53c2c 100644
--- a/arch/x86/mm/maccess.c
+++ b/arch/x86/mm/maccess.c
@@ -4,11 +4,6 @@
 #include <linux/kernel.h>
 
 #ifdef CONFIG_X86_64
-static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
-{
-	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
-}
-
 bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 {
 	unsigned long vaddr = (unsigned long)unsafe_src;
@@ -19,7 +14,7 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
 	 * we also need to include the userspace guard page.
 	 */
 	return vaddr >= TASK_SIZE_MAX + PAGE_SIZE &&
-	       canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
+	       __is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
 }
 #else
 bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [tip: perf/core] perf/x86/intel/pt: Relax address filter validation
  2022-01-31  7:24 ` [PATCH 1/5] perf/x86/intel/pt: Relax address filter validation Adrian Hunter
@ 2022-02-03 14:33   ` tip-bot2 for Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: tip-bot2 for Adrian Hunter @ 2022-02-03 14:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Adrian Hunter, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     c243cecb58e3905baeace8827201c14df8481e2a
Gitweb:        https://git.kernel.org/tip/c243cecb58e3905baeace8827201c14df8481e2a
Author:        Adrian Hunter <adrian.hunter@intel.com>
AuthorDate:    Mon, 31 Jan 2022 09:24:49 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 02 Feb 2022 13:11:42 +01:00

perf/x86/intel/pt: Relax address filter validation

The requirement for 64-bit address filters is that they are canonical
addresses. In other respects any address range is allowed which would
include user space addresses.

That can be useful for tracing virtual machine guests because address
filtering can be used to advantage in place of current privilege level
(CPL) filtering.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20220131072453.2839535-2-adrian.hunter@intel.com
---
 arch/x86/events/intel/pt.c | 63 +++++++++++++++++++++++++++++--------
 1 file changed, 50 insertions(+), 13 deletions(-)

diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c
index 7f406c1..0ebcf9a 100644
--- a/arch/x86/events/intel/pt.c
+++ b/arch/x86/events/intel/pt.c
@@ -13,6 +13,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/types.h>
+#include <linux/bits.h>
+#include <linux/limits.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 
@@ -1347,11 +1349,37 @@ static void pt_addr_filters_fini(struct perf_event *event)
 	event->hw.addr_filters = NULL;
 }
 
-static inline bool valid_kernel_ip(unsigned long ip)
+#ifdef CONFIG_X86_64
+static u64 canonical_address(u64 vaddr, u8 vaddr_bits)
 {
-	return virt_addr_valid(ip) && kernel_ip(ip);
+	return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
 }
 
+static u64 is_canonical_address(u64 vaddr, u8 vaddr_bits)
+{
+	return canonical_address(vaddr, vaddr_bits) == vaddr;
+}
+
+/* Clamp to a canonical address greater-than-or-equal-to the address given */
+static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
+{
+	return is_canonical_address(vaddr, vaddr_bits) ?
+	       vaddr :
+	       -BIT_ULL(vaddr_bits - 1);
+}
+
+/* Clamp to a canonical address less-than-or-equal-to the address given */
+static u64 clamp_to_le_canonical_addr(u64 vaddr, u8 vaddr_bits)
+{
+	return is_canonical_address(vaddr, vaddr_bits) ?
+	       vaddr :
+	       BIT_ULL(vaddr_bits - 1) - 1;
+}
+#else
+#define clamp_to_ge_canonical_addr(x, y) (x)
+#define clamp_to_le_canonical_addr(x, y) (x)
+#endif
+
 static int pt_event_addr_filters_validate(struct list_head *filters)
 {
 	struct perf_addr_filter *filter;
@@ -1366,14 +1394,6 @@ static int pt_event_addr_filters_validate(struct list_head *filters)
 		    filter->action == PERF_ADDR_FILTER_ACTION_START)
 			return -EOPNOTSUPP;
 
-		if (!filter->path.dentry) {
-			if (!valid_kernel_ip(filter->offset))
-				return -EINVAL;
-
-			if (!valid_kernel_ip(filter->offset + filter->size))
-				return -EINVAL;
-		}
-
 		if (++range > intel_pt_validate_hw_cap(PT_CAP_num_address_ranges))
 			return -EOPNOTSUPP;
 	}
@@ -1397,9 +1417,26 @@ static void pt_event_addr_filters_sync(struct perf_event *event)
 		if (filter->path.dentry && !fr[range].start) {
 			msr_a = msr_b = 0;
 		} else {
-			/* apply the offset */
-			msr_a = fr[range].start;
-			msr_b = msr_a + fr[range].size - 1;
+			unsigned long n = fr[range].size - 1;
+			unsigned long a = fr[range].start;
+			unsigned long b;
+
+			if (a > ULONG_MAX - n)
+				b = ULONG_MAX;
+			else
+				b = a + n;
+			/*
+			 * Apply the offset. 64-bit addresses written to the
+			 * MSRs must be canonical, but the range can encompass
+			 * non-canonical addresses. Since software cannot
+			 * execute at non-canonical addresses, adjusting to
+			 * canonical addresses does not affect the result of the
+			 * address filter.
+			 */
+			msr_a = clamp_to_ge_canonical_addr(a, boot_cpu_data.x86_virt_bits);
+			msr_b = clamp_to_le_canonical_addr(b, boot_cpu_data.x86_virt_bits);
+			if (msr_b < msr_a)
+				msr_a = msr_b = 0;
 		}
 
 		filters->filter[range].msr_a  = msr_a;

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-02-03 14:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-31  7:24 [PATCH 0/5] perf/core: Address filter fixes / changes Adrian Hunter
2022-01-31  7:24 ` [PATCH 1/5] perf/x86/intel/pt: Relax address filter validation Adrian Hunter
2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
2022-01-31  7:24 ` [PATCH 2/5] x86: Share definition of __is_canonical_address() Adrian Hunter
2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
2022-01-31  7:24 ` [PATCH 3/5] perf/core: Fix address filter parser for multiple filters Adrian Hunter
2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
2022-01-31  7:24 ` [PATCH 4/5] perf/x86/intel/pt: Fix address filter config for 32-bit kernel Adrian Hunter
2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
2022-01-31  7:24 ` [PATCH 5/5] perf/core: Allow kernel address filter when not filtering the kernel Adrian Hunter
2022-02-03 14:33   ` [tip: perf/core] " tip-bot2 for Adrian Hunter
2022-02-01 13:25 ` [PATCH 0/5] perf/core: Address filter fixes / changes Peter Zijlstra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).