Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V5 01/12] arm64: mm: Remove bit-masking optimisations for PAGE_OFFSET and VMEMMAP_START
From: Steve Capper @ 2019-08-07 15:55 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: crecklin, ard.biesheuvel, catalin.marinas, bhsharma, Steve Capper,
	maz, will
In-Reply-To: <20190807155524.5112-1-steve.capper@arm.com>

Currently there are assumptions about the alignment of VMEMMAP_START
and PAGE_OFFSET that won't be valid after this series is applied.

These assumptions are in the form of bitwise operators being used
instead of addition and subtraction when calculating addresses.

This patch replaces these bitwise operators with addition/subtraction.

Signed-off-by: Steve Capper <steve.capper@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

---

New in V4
---
 arch/arm64/include/asm/memory.h | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index b7ba75809751..d3a951dc9878 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -295,21 +295,20 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define _virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 #else
-#define __virt_to_pgoff(kaddr)	(((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
-#define __page_to_voff(kaddr)	(((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
+#define __virt_to_pgoff(kaddr)	(((u64)(kaddr) - PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
+#define __page_to_voff(kaddr)	(((u64)(kaddr) - VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
 
 #define page_to_virt(page)	({					\
 	unsigned long __addr =						\
-		((__page_to_voff(page)) | PAGE_OFFSET);			\
+		((__page_to_voff(page)) + PAGE_OFFSET);			\
 	unsigned long __addr_tag =					\
 		 __tag_set(__addr, page_kasan_tag(page));		\
 	((void *)__addr_tag);						\
 })
 
-#define virt_to_page(vaddr)	((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
+#define virt_to_page(vaddr)	((struct page *)((__virt_to_pgoff(vaddr)) + VMEMMAP_START))
 
-#define _virt_addr_valid(kaddr)	pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \
-					   + PHYS_OFFSET) >> PAGE_SHIFT)
+#define _virt_addr_valid(kaddr)	pfn_valid(__virt_to_phys((u64)(kaddr)) >> PAGE_SHIFT)
 #endif
 #endif
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH V5 02/12] arm64: mm: Flip kernel VA space
From: Steve Capper @ 2019-08-07 15:55 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: crecklin, ard.biesheuvel, catalin.marinas, bhsharma, Steve Capper,
	maz, will
In-Reply-To: <20190807155524.5112-1-steve.capper@arm.com>

In order to allow for a KASAN shadow that changes size at boot time, one
must fix the KASAN_SHADOW_END for both 48 & 52-bit VAs and "grow" the
start address. Also, it is highly desirable to maintain the same
function addresses in the kernel .text between VA sizes. Both of these
requirements necessitate us to flip the kernel address space halves s.t.
the direct linear map occupies the lower addresses.

This patch puts the direct linear map in the lower addresses of the
kernel VA range and everything else in the higher ranges.

We need to adjust:
 *) KASAN shadow region placement logic,
 *) KASAN_SHADOW_OFFSET computation logic,
 *) virt_to_phys, phys_to_virt checks,
 *) page table dumper.

These are all small changes, that need to take place atomically, so they
are bundled into this commit.

As part of the re-arrangement, a guard region of 2MB (to preserve
alignment for fixed map) is added after the vmemmap. Otherwise the
vmemmap could intersect with IS_ERR pointers.

Signed-off-by: Steve Capper <steve.capper@arm.com>

---
Changed in V5 - simplify the kernel page table dumper patch as we have
2MB gap at the end of the kernel virtual address space.

Changed in V4 - we add a guard region after vmemmap to avoid ambiguity
with error pointers
---
 arch/arm64/Makefile              | 2 +-
 arch/arm64/include/asm/memory.h  | 8 ++++----
 arch/arm64/include/asm/pgtable.h | 2 +-
 arch/arm64/kernel/hibernate.c    | 2 +-
 arch/arm64/mm/dump.c             | 5 +++--
 arch/arm64/mm/init.c             | 9 +--------
 arch/arm64/mm/kasan_init.c       | 6 +++---
 arch/arm64/mm/mmu.c              | 4 ++--
 8 files changed, 16 insertions(+), 22 deletions(-)

diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index bb1f1dbb34e8..b2400f9c1213 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -130,7 +130,7 @@ KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT)
 #				 - (1 << (64 - KASAN_SHADOW_SCALE_SHIFT))
 # in 32-bit arithmetic
 KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \
-	(0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 32))) \
+	(0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 1 - 32))) \
 	+ (1 << ($(CONFIG_ARM64_VA_BITS) - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) \
 	- (1 << (64 - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) )) )
 
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index d3a951dc9878..98a87f0f40d5 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -38,9 +38,9 @@
  */
 #define VA_BITS			(CONFIG_ARM64_VA_BITS)
 #define VA_START		(UL(0xffffffffffffffff) - \
-	(UL(1) << VA_BITS) + 1)
-#define PAGE_OFFSET		(UL(0xffffffffffffffff) - \
 	(UL(1) << (VA_BITS - 1)) + 1)
+#define PAGE_OFFSET		(UL(0xffffffffffffffff) - \
+	(UL(1) << VA_BITS) + 1)
 #define KIMAGE_VADDR		(MODULES_END)
 #define BPF_JIT_REGION_START	(VA_START + KASAN_SHADOW_SIZE)
 #define BPF_JIT_REGION_SIZE	(SZ_128M)
@@ -48,7 +48,7 @@
 #define MODULES_END		(MODULES_VADDR + MODULES_VSIZE)
 #define MODULES_VADDR		(BPF_JIT_REGION_END)
 #define MODULES_VSIZE		(SZ_128M)
-#define VMEMMAP_START		(PAGE_OFFSET - VMEMMAP_SIZE)
+#define VMEMMAP_START		(-VMEMMAP_SIZE - SZ_2M)
 #define PCI_IO_END		(VMEMMAP_START - SZ_2M)
 #define PCI_IO_START		(PCI_IO_END - PCI_IO_SIZE)
 #define FIXADDR_TOP		(PCI_IO_START - SZ_2M)
@@ -227,7 +227,7 @@ extern u64			vabits_user;
  * space. Testing the top bit for the start of the region is a
  * sufficient check.
  */
-#define __is_lm_address(addr)	(!!((addr) & BIT(VA_BITS - 1)))
+#define __is_lm_address(addr)	(!((addr) & BIT(VA_BITS - 1)))
 
 #define __lm_to_phys(addr)	(((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
 #define __kimg_to_phys(addr)	((addr) - kimage_voffset)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 3f5461f7b560..d274ea9a5f86 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -21,7 +21,7 @@
  *	and fixed mappings
  */
 #define VMALLOC_START		(MODULES_END)
-#define VMALLOC_END		(PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
+#define VMALLOC_END		(- PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
 
 #define vmemmap			((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
 
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 9341fcc6e809..e130db05d932 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -496,7 +496,7 @@ int swsusp_arch_resume(void)
 		rc = -ENOMEM;
 		goto out;
 	}
-	rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
+	rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, VA_START);
 	if (rc)
 		goto out;
 
diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index 82b3a7fdb4a6..beec87488e97 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -26,6 +26,8 @@
 #include <asm/ptdump.h>
 
 static const struct addr_marker address_markers[] = {
+	{ PAGE_OFFSET,			"Linear Mapping start" },
+	{ VA_START,			"Linear Mapping end" },
 #ifdef CONFIG_KASAN
 	{ KASAN_SHADOW_START,		"Kasan shadow start" },
 	{ KASAN_SHADOW_END,		"Kasan shadow end" },
@@ -42,7 +44,6 @@ static const struct addr_marker address_markers[] = {
 	{ VMEMMAP_START,		"vmemmap start" },
 	{ VMEMMAP_START + VMEMMAP_SIZE,	"vmemmap end" },
 #endif
-	{ PAGE_OFFSET,			"Linear mapping" },
 	{ -1,				NULL },
 };
 
@@ -376,7 +377,7 @@ static void ptdump_initialize(void)
 static struct ptdump_info kernel_ptdump_info = {
 	.mm		= &init_mm,
 	.markers	= address_markers,
-	.base_addr	= VA_START,
+	.base_addr	= PAGE_OFFSET,
 };
 
 void ptdump_check_wx(void)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f3c795278def..62927ed02229 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -301,7 +301,7 @@ static void __init fdt_enforce_memory_region(void)
 
 void __init arm64_memblock_init(void)
 {
-	const s64 linear_region_size = -(s64)PAGE_OFFSET;
+	const s64 linear_region_size = BIT(VA_BITS - 1);
 
 	/* Handle linux,usable-memory-range property */
 	fdt_enforce_memory_region();
@@ -309,13 +309,6 @@ void __init arm64_memblock_init(void)
 	/* Remove memory above our supported physical address size */
 	memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX);
 
-	/*
-	 * Ensure that the linear region takes up exactly half of the kernel
-	 * virtual address space. This way, we can distinguish a linear address
-	 * from a kernel/module/vmalloc address by testing a single bit.
-	 */
-	BUILD_BUG_ON(linear_region_size != BIT(VA_BITS - 1));
-
 	/*
 	 * Select a suitable value for the base of physical memory.
 	 */
diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 6cf97b904ebb..05edfe9b02e4 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -225,10 +225,10 @@ void __init kasan_init(void)
 	kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
 			   early_pfn_to_nid(virt_to_pfn(lm_alias(_text))));
 
-	kasan_populate_early_shadow((void *)KASAN_SHADOW_START,
-				    (void *)mod_shadow_start);
+	kasan_populate_early_shadow(kasan_mem_to_shadow((void *) VA_START),
+				   (void *)mod_shadow_start);
 	kasan_populate_early_shadow((void *)kimg_shadow_end,
-				    kasan_mem_to_shadow((void *)PAGE_OFFSET));
+				   (void *)KASAN_SHADOW_END);
 
 	if (kimg_shadow_start > mod_shadow_end)
 		kasan_populate_early_shadow((void *)mod_shadow_end,
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 750a69dde39b..1d4247f9a496 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -398,7 +398,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
 static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
 				  phys_addr_t size, pgprot_t prot)
 {
-	if (virt < VMALLOC_START) {
+	if ((virt >= VA_START) && (virt < VMALLOC_START)) {
 		pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n",
 			&phys, virt);
 		return;
@@ -425,7 +425,7 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
 static void update_mapping_prot(phys_addr_t phys, unsigned long virt,
 				phys_addr_t size, pgprot_t prot)
 {
-	if (virt < VMALLOC_START) {
+	if ((virt >= VA_START) && (virt < VMALLOC_START)) {
 		pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n",
 			&phys, virt);
 		return;
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH V5 00/12] 52-bit kernel + user VAs
From: Steve Capper @ 2019-08-07 15:55 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: crecklin, ard.biesheuvel, catalin.marinas, bhsharma, Steve Capper,
	maz, will

This patch series adds support for 52-bit kernel VAs using some of the
machinery already introduced by the 52-bit userspace VA code in 5.0.

As 52-bit virtual address support is an optional hardware feature,
software support for 52-bit kernel VAs needs to be deduced at early boot
time. If HW support is not available, the kernel falls back to 48-bit.

A significant proportion of this series focuses on "de-constifying"
VA_BITS related constants.

In order to allow for a KASAN shadow that changes size at boot time, one
must fix the KASAN_SHADOW_END for both 48 & 52-bit VAs and "grow" the
start address. Also, it is highly desirable to maintain the same
function addresses in the kernel .text between VA sizes. Both of these
requirements necessitate us to flip the kernel address space halves s.t.
the direct linear map occupies the lower addresses.

In V5 of this series the, now redundant, vabits_user was removed by an
extra patch.

In V4 of this series, an extra documentation patch is added to explain
both the layout of the memory and the implementation of 52-bit support.
Also added is a guard region after VMEMMAP to avoid ambiguity with
IS_ERR style pointers. Finally the bitmask optimisations for VMEMMAP and
PAGE_OFFSET are replaced with addition/subtraction in a new first patch
for the series.

In V3 of this series, the 52-bit user/48-bit kernel option is removed
and we are left with a single 52-bit VA option instead. The offset_ttbr1
conditional logic has been re-worked to directly read a system register
rather than rely on the alternative framework (I couldn't actually see a
hotpath calling offset_ttbr1 and some parts of the early boot relied on
offset_ttbr1 before the alternatives framework was called). Also some
spurious de-constifying changes have been removed.

In V2 of this series (apologies for the long delay from V1), the major
change is that PAGE_OFFSET is retained as a constant. This allows for
much faster virt_to_page computations. This is achieved by expanding the
size of the VMEMMAP region to accommodate a disjoint 52-bit/48-bit
direct linear map. This has been found to work well in my testing, but I
would appreciate any feedback on this if it needs changing. To aid with
git bisect, this logic is broken down into a few smaller patches

Steve Capper (12):
  arm64: mm: Remove bit-masking optimisations for PAGE_OFFSET and
    VMEMMAP_START
  arm64: mm: Flip kernel VA space
  arm64: kasan: Switch to using KASAN_SHADOW_OFFSET
  arm64: dump: De-constify VA_START and KASAN_SHADOW_START
  arm64: mm: Introduce VA_BITS_MIN
  arm64: mm: Introduce vabits_actual
  arm64: mm: Logic to make offset_ttbr1 conditional
  arm64: mm: Separate out vmemmap
  arm64: mm: Modify calculation of VMEMMAP_SIZE
  arm64: mm: Introduce 52-bit Kernel VAs
  arm64: mm: Remove vabits_user
  docs: arm64: Add layout and 52-bit info to memory document

 Documentation/arm64/kasan-offsets.sh   |  27 ++++++
 Documentation/arm64/memory.rst         | 123 +++++++++++++++++++------
 arch/arm64/Kconfig                     |  31 +++++--
 arch/arm64/Makefile                    |   8 --
 arch/arm64/include/asm/assembler.h     |  17 +++-
 arch/arm64/include/asm/efi.h           |   4 +-
 arch/arm64/include/asm/kasan.h         |  11 +--
 arch/arm64/include/asm/memory.h        |  58 +++++++-----
 arch/arm64/include/asm/mmu_context.h   |   4 +-
 arch/arm64/include/asm/pgtable-hwdef.h |   2 +-
 arch/arm64/include/asm/pgtable.h       |   6 +-
 arch/arm64/include/asm/pointer_auth.h  |   2 +-
 arch/arm64/include/asm/processor.h     |   4 +-
 arch/arm64/kernel/head.S               |  12 +--
 arch/arm64/kernel/hibernate-asm.S      |   8 +-
 arch/arm64/kernel/hibernate.c          |   2 +-
 arch/arm64/kernel/kaslr.c              |   6 +-
 arch/arm64/kvm/va_layout.c             |  14 +--
 arch/arm64/mm/dump.c                   |  22 ++++-
 arch/arm64/mm/fault.c                  |   5 +-
 arch/arm64/mm/init.c                   |  29 ++++--
 arch/arm64/mm/kasan_init.c             |   9 +-
 arch/arm64/mm/mmu.c                    |   9 +-
 arch/arm64/mm/proc.S                   |  11 ++-
 24 files changed, 289 insertions(+), 135 deletions(-)
 create mode 100644 Documentation/arm64/kasan-offsets.sh

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH v7 2/2] arm64: Relax Documentation/arm64/tagged-pointers.rst
From: Catalin Marinas @ 2019-08-07 15:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-arch, linux-doc, Szabolcs Nagy, Andrey Konovalov,
	Kevin Brodsky, Will Deacon, Dave Hansen, Vincenzo Frascino
In-Reply-To: <20190807155321.9648-1-catalin.marinas@arm.com>

From: Vincenzo Frascino <vincenzo.frascino@arm.com>

On arm64 the TCR_EL1.TBI0 bit has been always enabled hence
the userspace (EL0) is allowed to set a non-zero value in the
top byte but the resulting pointers are not allowed at the
user-kernel syscall ABI boundary.

With the relaxed ABI proposed in this set, it is now possible to pass
tagged pointers to the syscalls, when these pointers are in memory
ranges obtained by an anonymous (MAP_ANONYMOUS) mmap().

Relax the requirements described in tagged-pointers.rst to be compliant
with the behaviours guaranteed by the ARM64 Tagged Address ABI.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
[catalin.marinas@arm.com: minor tweaks]
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
 Documentation/arm64/tagged-pointers.rst | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index 2acdec3ebbeb..82a3eff71a70 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -20,7 +20,8 @@ Passing tagged addresses to the kernel
 --------------------------------------
 
 All interpretation of userspace memory addresses by the kernel assumes
-an address tag of 0x00.
+an address tag of 0x00, unless the application enables the AArch64
+Tagged Address ABI explicitly.
 
 This includes, but is not limited to, addresses found in:
 
@@ -33,18 +34,23 @@ This includes, but is not limited to, addresses found in:
  - the frame pointer (x29) and frame records, e.g. when interpreting
    them to generate a backtrace or call graph.
 
-Using non-zero address tags in any of these locations may result in an
-error code being returned, a (fatal) signal being raised, or other modes
-of failure.
+Using non-zero address tags in any of these locations when the
+userspace application did not enable the AArch64 Tagged Address ABI may
+result in an error code being returned, a (fatal) signal being raised,
+or other modes of failure.
 
-For these reasons, passing non-zero address tags to the kernel via
-system calls is forbidden, and using a non-zero address tag for sp is
-strongly discouraged.
+For these reasons, when the AArch64 Tagged Address ABI is disabled,
+passing non-zero address tags to the kernel via system calls is
+forbidden, and using a non-zero address tag for sp is strongly
+discouraged.
 
 Programs maintaining a frame pointer and frame records that use non-zero
 address tags may suffer impaired or inaccurate debug and profiling
 visibility.
 
+The AArch64 Tagged Address ABI description and the guarantees it
+provides can be found in: Documentation/arm64/tagged-address-abi.rst.
+
 
 Preserving tags
 ---------------
@@ -59,6 +65,9 @@ be preserved.
 The architecture prevents the use of a tagged PC, so the upper byte will
 be set to a sign-extension of bit 55 on exception return.
 
+This behaviour is preserved when the AArch64 Tagged Address ABI is
+enabled.
+
 
 Other considerations
 --------------------

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v7 1/2] arm64: Define Documentation/arm64/tagged-address-abi.rst
From: Catalin Marinas @ 2019-08-07 15:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-arch, linux-doc, Szabolcs Nagy, Andrey Konovalov,
	Kevin Brodsky, Will Deacon, Dave Hansen, Vincenzo Frascino
In-Reply-To: <20190807155321.9648-1-catalin.marinas@arm.com>

From: Vincenzo Frascino <vincenzo.frascino@arm.com>

On arm64 the TCR_EL1.TBI0 bit has been always enabled hence
the userspace (EL0) is allowed to set a non-zero value in the
top byte but the resulting pointers are not allowed at the
user-kernel syscall ABI boundary.

With the relaxed ABI proposed through this document, it is now possible
to pass tagged pointers to the syscalls, when these pointers are in
memory ranges obtained by an anonymous (MAP_ANONYMOUS) mmap().

This change in the ABI requires a mechanism to requires the userspace
to opt-in to such an option.

Specify and document the way in which sysctl and prctl() can be used
in combination to allow the userspace to opt-in this feature.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
[catalin.marinas@arm.com: some rewording, dropped MAP_PRIVATE]
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
 Documentation/arm64/tagged-address-abi.rst | 151 +++++++++++++++++++++
 1 file changed, 151 insertions(+)
 create mode 100644 Documentation/arm64/tagged-address-abi.rst

diff --git a/Documentation/arm64/tagged-address-abi.rst b/Documentation/arm64/tagged-address-abi.rst
new file mode 100644
index 000000000000..f91a5d2ac865
--- /dev/null
+++ b/Documentation/arm64/tagged-address-abi.rst
@@ -0,0 +1,151 @@
+==========================
+AArch64 TAGGED ADDRESS ABI
+==========================
+
+Author: Vincenzo Frascino <vincenzo.frascino@arm.com>
+
+Date: 25 July 2019
+
+This document describes the usage and semantics of the Tagged Address
+ABI on AArch64 Linux.
+
+1. Introduction
+---------------
+
+On AArch64 the TCR_EL1.TBI0 bit has always been enabled, allowing userspace
+(EL0) to perform memory accesses through 64-bit pointers with a non-zero
+top byte. Such tagged pointers, however, were not allowed at the
+user-kernel syscall ABI boundary.
+
+This document describes the relaxation of the syscall ABI that allows
+userspace to pass certain tagged pointers to kernel syscalls, as described
+in section 2.
+
+2. AArch64 Tagged Address ABI
+-----------------------------
+
+From the kernel syscall interface perspective and for the purposes of this
+document, a "valid tagged pointer" is a pointer with a potentially non-zero
+top-byte that references an address in the user process address space
+obtained in one of the following ways:
+
+- mmap() done by the process itself (or its parent), where either:
+
+  - flags have the **MAP_ANONYMOUS** bit set
+  - the file descriptor refers to a regular file (including those returned
+    by memfd_create()) or **/dev/zero**
+
+- brk() system call done by the process itself (i.e. the heap area between
+  the initial location of the program break at process creation and its
+  current location).
+
+- any memory mapped by the kernel in the address space of the process
+  during creation and with the same restrictions as for mmap() above (e.g.
+  data, bss, stack).
+
+The AArch64 Tagged Address ABI is an opt-in feature and an application can
+control it via **prctl()** as follows:
+
+- **PR_SET_TAGGED_ADDR_CTRL**: enable or disable the AArch64 Tagged Address
+  ABI for the calling process.
+
+  The (unsigned int) arg2 argument is a bit mask describing the control mode
+  used:
+
+  - **PR_TAGGED_ADDR_ENABLE**: enable AArch64 Tagged Address ABI. Default
+    status is disabled.
+
+  The arguments arg3, arg4, and arg5 are ignored.
+
+- **PR_GET_TAGGED_ADDR_CTRL**: get the status of the AArch64 Tagged Address
+  ABI for the calling process.
+
+  The arguments arg2, arg3, arg4, and arg5 are ignored.
+
+The prctl(PR_SET_TAGGED_ADDR_CTRL, ...) will return -EINVAL if the
+AArch64 Tagged Address ABI is not available
+(CONFIG_ARM64_TAGGED_ADDR_ABI disabled or sysctl abi.tagged_addr=0).
+
+The ABI properties set by the mechanism described above are inherited by
+threads of the same application and fork()'ed children but cleared by
+execve().
+
+Opting in (the prctl() option described above only) to or out of the
+AArch64 Tagged Address ABI can be disabled globally at runtime using the
+sysctl interface:
+
+- **abi.tagged_addr**: a new sysctl interface that can be used to prevent
+  applications from enabling or disabling the relaxed ABI. The sysctl
+  supports the following configuration options:
+
+  - **0**: disable the prctl(PR_SET_TAGGED_ADDR_CTRL) option to
+    enable/disable the AArch64 Tagged Address ABI globally
+
+  - **1** (Default): enable the prctl(PR_SET_TAGGED_ADDR_CTRL) option to
+    enable/disable the AArch64 Tagged Address ABI globally
+
+  Note that this sysctl does not affect the status of the AArch64 Tagged
+  Address ABI of the running processes.
+
+When a process has successfully enabled the new ABI by invoking
+prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE), the following
+behaviours are guaranteed:
+
+- Every currently available syscall, except the cases mentioned in section
+  3, can accept any valid tagged pointer. The same rule is applicable to
+  any syscall introduced in the future.
+
+- The syscall behaviour is undefined for non valid tagged pointers.
+
+- Every valid tagged pointer is expected to work as an untagged one.
+
+A definition of the meaning of tagged pointers on AArch64 can be found in:
+Documentation/arm64/tagged-pointers.txt.
+
+3. AArch64 Tagged Address ABI Exceptions
+-----------------------------------------
+
+The behaviour described in section 2, with particular reference to the
+acceptance by the syscalls of any valid tagged pointer, is not applicable
+to the following cases:
+
+- mmap() addr parameter.
+
+- mremap() new_address parameter.
+
+- prctl(PR_SET_MM, ``*``, ...) other than arg2 PR_SET_MM_MAP and
+  PR_SET_MM_MAP_SIZE.
+
+- prctl(PR_SET_MM, PR_SET_MM_MAP{,_SIZE}, ...) struct prctl_mm_map fields.
+
+Any attempt to use non-zero tagged pointers will lead to undefined
+behaviour.
+
+4. Example of correct usage
+---------------------------
+.. code-block:: c
+
+   void main(void)
+   {
+           static int tbi_enabled = 0;
+           unsigned long tag = 0;
+
+           char *ptr = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+                            MAP_ANONYMOUS, -1, 0);
+
+           if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE,
+                     0, 0, 0) == 0)
+                   tbi_enabled = 1;
+
+           if (ptr == (void *)-1) /* MAP_FAILED */
+                   return -1;
+
+           if (tbi_enabled)
+                   tag = rand() & 0xff;
+
+           ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT));
+
+           *ptr = 'a';
+
+           ...
+   }

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH v7 0/2] arm64 tagged address ABI
From: Catalin Marinas @ 2019-08-07 15:53 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: linux-arch, linux-doc, Szabolcs Nagy, Andrey Konovalov,
	Kevin Brodsky, Will Deacon, Dave Hansen, Vincenzo Frascino

Hi,

Thanks for the feedback so far. This is an updated series documenting
the AArch64 Tagged Address ABI as implemented by these patches:

http://lkml.kernel.org/r/cover.1563904656.git.andreyknvl@google.com

Version 6 of the documentation series is available here:

http://lkml.kernel.org/r/20190725135044.24381-1-vincenzo.frascino@arm.com

Changes in v7:

- Dropped the MAP_PRIVATE requirements for tagged pointers for both
  anonymous and file mappings. One reason is that we can't enforce such
  restriction anyway. The other reason is that a future series
  implementing support for the hardware MTE will detect
  incompatibilities of the new PROT_MTE flag with various mmap()
  options.

- As a consequence of the above, I removed Szabolcs ack as I'm not sure
  he's ok with the change.

- Clarified the sysctl and prctl() interaction and reordered the
  descriptions.

- Reworded the prctl(PR_SET_MM) restrictions.

- Removed the description of the tag preservation from the first patch
  as it didn't really make sense (the syscall ABI has always preserved
  all registers other than x0 on return to user).

- s/ARM64/AArch64/ for consistency with the tagged-pointers.rst
  document.

- Other minor rewordings.

Vincenzo Frascino (2):
  arm64: Define Documentation/arm64/tagged-address-abi.rst
  arm64: Relax Documentation/arm64/tagged-pointers.rst

 Documentation/arm64/tagged-address-abi.rst | 151 +++++++++++++++++++++
 Documentation/arm64/tagged-pointers.rst    |  23 +++-
 2 files changed, 167 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/arm64/tagged-address-abi.rst


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] arm64: Disable big endian builds with clang
From: Mark Rutland @ 2019-08-07 15:43 UTC (permalink / raw)
  To: Mark Brown
  Cc: Tri Vo, Catalin Marinas, Nick Desaulniers, clang-built-linux,
	Matt Hart, Nathan Chancellor, Will Deacon, linux-arm-kernel
In-Reply-To: <20190807152934.GF4048@sirena.co.uk>

On Wed, Aug 07, 2019 at 04:29:34PM +0100, Mark Brown wrote:
> On Wed, Aug 07, 2019 at 02:56:19PM +0100, Mark Rutland wrote:
> > On Wed, Aug 07, 2019 at 02:05:27PM +0100, Mark Brown wrote:
> You can see the exact image being used in the reports I linked:
> 
> 	https://storage.kernelci.org/next/master/next-20190730/arm64/defconfig+CONFIG_CPU_BIG_ENDIAN=y/clang-8/Image

That confirms what Robin suggested [1] from looking at the config: this
is a little-endian kernel.

The Image header flags the big-endian bit is 0, and it succcessfully
boots with a little-endian rootfs; log below.

Thanks,
Mark.

[1] https://lore.kernel.org/r/ec7bef46-7dcf-d165-b772-b4fd6055d964@arm.com

---->8----
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x431f0af1]
[    0.000000] Linux version 5.3.0-rc2-next-20190730 (KernelCI@30d217901839) (clang version 8.0.1-svn359952-1~exp1~20190504004501.65 (branches/release_80)) #1 SMP PREEMPT Tue Jul 30 06:50:57 UTC 2019
[    0.000000] Machine model: linux,dummy-virt
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 32 MiB at 0x00000000be000000
[    0.000000] earlycon: pl11 at MMIO 0x0000000009000000 (options '')
[    0.000000] printk: bootconsole [pl11] enabled
[    0.000000] NUMA: No NUMA configuration found
[    0.000000] NUMA: Faking a node at [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] NUMA: NODE_DATA [mem 0xbdbf3840-0xbdbf4fff]
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] On node 0 totalpages: 524288
[    0.000000]   DMA32 zone: 8192 pages used for memmap
[    0.000000]   DMA32 zone: 0 pages reserved
[    0.000000]   DMA32 zone: 524288 pages, LIFO batch:63
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.0 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] psci: SMC Calling Convention v1.1
[    0.000000] percpu: Embedded 23 pages/cpu s56856 r8192 d29160 u94208
[    0.000000] pcpu-alloc: s56856 r8192 d29160 u94208 alloc=23*4096
[    0.000000] pcpu-alloc: [0] 0
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] CPU features: detected: GIC system register CPU interface
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 516096
[    0.000000] Policy zone: DMA32
[    0.000000] Kernel command line: loglevel=9 rodata=full earlycon root=/dev/vda
[    0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
[    0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 1997596K/2097152K available (12028K kernel code, 1912K rwdata, 6004K rodata, 5184K init, 448K bss, 66788K reserved, 32768K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] rcu: Preemptible hierarchical RCU implementation.
[    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=1.
[    0.000000]  Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] GICv3: Distributor has no Range Selector support
[    0.000000] GICv3: no VLPI support, no direct LPI support
[    0.000000] GICv3: CPU0: found redistributor 0 region 0:0x00000000080a0000
[    0.000000] ITS [mem 0x08080000-0x0809ffff]
[    0.000000] ITS@0x0000000008080000: allocated 8192 Devices @bb030000 (indirect, esz 8, psz 64K, shr 1)
[    0.000000] ITS@0x0000000008080000: allocated 8192 Interrupt Collections @bb040000 (flat, esz 8, psz 64K, shr 1)
[    0.000000] GICv3: using LPI property table @0x00000000bb050000
[    0.000000] GICv3: CPU0: using allocated LPI pending table @0x00000000bb060000
[    0.000000] random: get_random_bytes called from start_kernel+0x1d4/0x39c with crng_init=0
[    0.000000] arch_timer: cp15 timer(s) running at 200.00MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x2e2049d3e8, max_idle_ns: 440795210634 ns
[    0.000008] sched_clock: 56 bits at 200MHz, resolution 5ns, wraps every 4398046511102ns
[    0.003286] Console: colour dummy device 80x25
[    0.004711] printk: console [tty0] enabled
[    0.006114] printk: bootconsole [pl11] disabled
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x431f0af1]
[    0.000000] Linux version 5.3.0-rc2-next-20190730 (KernelCI@30d217901839) (clang version 8.0.1-svn359952-1~exp1~20190504004501.65 (branches/release_80)) #1 SMP PREEMPT Tue Jul 30 06:50:57 UTC 2019
[    0.000000] Machine model: linux,dummy-virt
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 32 MiB at 0x00000000be000000
[    0.000000] earlycon: pl11 at MMIO 0x0000000009000000 (options '')
[    0.000000] printk: bootconsole [pl11] enabled
[    0.000000] NUMA: No NUMA configuration found
[    0.000000] NUMA: Faking a node at [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] NUMA: NODE_DATA [mem 0xbdbf3840-0xbdbf4fff]
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x00000000bfffffff]
[    0.000000] On node 0 totalpages: 524288
[    0.000000]   DMA32 zone: 8192 pages used for memmap
[    0.000000]   DMA32 zone: 0 pages reserved
[    0.000000]   DMA32 zone: 524288 pages, LIFO batch:63
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.0 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] psci: SMC Calling Convention v1.1
[    0.000000] percpu: Embedded 23 pages/cpu s56856 r8192 d29160 u94208
[    0.000000] pcpu-alloc: s56856 r8192 d29160 u94208 alloc=23*4096
[    0.000000] pcpu-alloc: [0] 0
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] CPU features: detected: GIC system register CPU interface
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 516096
[    0.000000] Policy zone: DMA32
[    0.000000] Kernel command line: loglevel=9 rodata=full earlycon root=/dev/vda
[    0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
[    0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 1997596K/2097152K available (12028K kernel code, 1912K rwdata, 6004K rodata, 5184K init, 448K bss, 66788K reserved, 32768K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] rcu: Preemptible hierarchical RCU implementation.
[    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=1.
[    0.000000]  Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] GICv3: Distributor has no Range Selector support
[    0.000000] GICv3: no VLPI support, no direct LPI support
[    0.000000] GICv3: CPU0: found redistributor 0 region 0:0x00000000080a0000
[    0.000000] ITS [mem 0x08080000-0x0809ffff]
[    0.000000] ITS@0x0000000008080000: allocated 8192 Devices @bb030000 (indirect, esz 8, psz 64K, shr 1)
[    0.000000] ITS@0x0000000008080000: allocated 8192 Interrupt Collections @bb040000 (flat, esz 8, psz 64K, shr 1)
[    0.000000] GICv3: using LPI property table @0x00000000bb050000
[    0.000000] GICv3: CPU0: using allocated LPI pending table @0x00000000bb060000
[    0.000000] random: get_random_bytes called from start_kernel+0x1d4/0x39c with crng_init=0
[    0.000000] arch_timer: cp15 timer(s) running at 200.00MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x2e2049d3e8, max_idle_ns: 440795210634 ns
[    0.000008] sched_clock: 56 bits at 200MHz, resolution 5ns, wraps every 4398046511102ns
[    0.003286] Console: colour dummy device 80x25
[    0.004711] printk: console [tty0] enabled
[    0.006114] printk: bootconsole [pl11] disabled
[    0.007538] Calibrating delay loop (skipped), value calculated using timer frequency.. 400.00 BogoMIPS (lpj=800000)
[    0.007551] pid_max: default: 32768 minimum: 301
[    0.007581] LSM: Security Framework initializing
[    0.007608] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.007620] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.031972] ASID allocator initialised with 32768 entries
[    0.040072] rcu: Hierarchical SRCU implementation.
[    0.048261] Platform MSI: its@8080000 domain created
[    0.048294] PCI/MSI: /intc@8000000/its@8080000 domain created
[    0.048599] EFI services will not be available.
[    0.056343] smp: Bringing up secondary CPUs ...
[    0.056358] smp: Brought up 1 node, 1 CPU
[    0.056364] SMP: Total of 1 processors activated.
[    0.056372] CPU features: detected: Privileged Access Never
[    0.056378] CPU features: detected: LSE atomic instructions
[    0.056385] CPU features: detected: RAS Extension Support
[    0.056390] CPU features: detected: CRC32 instructions
[    0.056422] CPU: All CPU(s) started at EL1
[    0.056433] alternatives: patching kernel code
[    0.060214] devtmpfs: initialized
[    0.064667] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.064698] futex hash table entries: 256 (order: 2, 16384 bytes, linear)
[    0.065319] pinctrl core: initialized pinctrl subsystem
[    0.065982] DMI not present or invalid.
[    0.066218] NET: Registered protocol family 16
[    0.066370] audit: initializing netlink subsys (disabled)
[    0.068996] audit: type=2000 audit(0.064:1): state=initialized audit_enabled=0 res=1
[    0.073011] cpuidle: using governor menu
[    0.073154] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.074272] DMA: preallocated 256 KiB pool for atomic allocations
[    0.074866] Serial: AMBA PL011 UART driver
[    0.080484] 9000000.pl011: ttyAMA0 at MMIO 0x9000000 (irq = 39, base_baud = 0) is a PL011 rev1
[    0.229613] printk: console [ttyAMA0] enabled
[    0.239415] HugeTLB registered 1.00 GiB page size, pre-allocated 0 pages
[    0.241407] HugeTLB registered 32.0 MiB page size, pre-allocated 0 pages
[    0.243419] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages
[    0.245647] HugeTLB registered 64.0 KiB page size, pre-allocated 0 pages
[    0.255900] cryptd: max_cpu_qlen set to 1000
[    0.268422] ACPI: Interpreter disabled.
[    0.272279] vgaarb: loaded
[    0.273044] SCSI subsystem initialized
[    0.276232] libata version 3.00 loaded.
[    0.277368] usbcore: registered new interface driver usbfs
[    0.278868] usbcore: registered new interface driver hub
[    0.280448] usbcore: registered new device driver usb
[    0.282241] pps_core: LinuxPPS API ver. 1 registered
[    0.283441] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.285880] PTP clock support registered
[    0.286815] EDAC MC: Ver: 3.0.0
[    0.294074] FPGA manager framework
[    0.295226] Advanced Linux Sound Architecture Driver Initialized.
[    0.297068] clocksource: Switched to clocksource arch_sys_counter
[    0.298920] VFS: Disk quotas dquot_6.6.0
[    0.300084] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.302592] pnp: PnP ACPI: disabled
[    0.305599] thermal_sys: Registered thermal governor 'step_wise'
[    0.305601] thermal_sys: Registered thermal governor 'power_allocator'
[    0.307263] NET: Registered protocol family 2
[    0.310373] tcp_listen_portaddr_hash hash table entries: 1024 (order: 2, 16384 bytes, linear)
[    0.312314] TCP established hash table entries: 16384 (order: 5, 131072 bytes, linear)
[    0.314627] TCP bind hash table entries: 16384 (order: 6, 262144 bytes, linear)
[    0.316540] TCP: Hash tables configured (established 16384 bind 16384)
[    0.318499] UDP hash table entries: 1024 (order: 3, 32768 bytes, linear)
[    0.320465] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes, linear)
[    0.322749] NET: Registered protocol family 1
[    0.336608] RPC: Registered named UNIX socket transport module.
[    0.338472] RPC: Registered udp transport module.
[    0.339675] RPC: Registered tcp transport module.
[    0.340980] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    0.343132] PCI: CLS 0 bytes, default 64
[    0.344482] hw perfevents: enabled with armv8_pmuv3 PMU driver, 7 counters available
[    0.347065] kvm [1]: HYP mode not available
[    0.351832] Initialise system trusted keyrings
[    0.352989] workingset: timestamp_bits=44 max_order=19 bucket_order=0
[    0.357762] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.363821] NFS: Registering the id_resolver key type
[    0.365144] Key type id_resolver registered
[    0.365963] Key type id_legacy registered
[    0.366969] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    0.368424] 9p: Installing v9fs 9p2000 file system support
[    0.378865] Key type asymmetric registered
[    0.379958] Asymmetric key parser 'x509' registered
[    0.381016] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
[    0.383497] io scheduler mq-deadline registered
[    0.384538] io scheduler kyber registered
[    0.388367] pl061_gpio 9030000.pl061: PL061 GPIO chip registered
[    0.390238] pci-host-generic 4010000000.pcie: host bridge /pcie@10000000 ranges:
[    0.391780] pci-host-generic 4010000000.pcie:    IO 0x3eff0000..0x3effffff -> 0x00000000
[    0.393604] pci-host-generic 4010000000.pcie:   MEM 0x10000000..0x3efeffff -> 0x10000000
[    0.395182] pci-host-generic 4010000000.pcie:   MEM 0x8000000000..0xffffffffff -> 0x8000000000
[    0.396830] pci-host-generic 4010000000.pcie: ECAM at [mem 0x4010000000-0x401fffffff] for [bus 00-ff]
[    0.399261] pci-host-generic 4010000000.pcie: PCI host bridge to bus 0000:00
[    0.400526] pci_bus 0000:00: root bus resource [bus 00-ff]
[    0.401684] pci_bus 0000:00: root bus resource [io  0x0000-0xffff]
[    0.402759] pci_bus 0000:00: root bus resource [mem 0x10000000-0x3efeffff]
[    0.404202] pci_bus 0000:00: root bus resource [mem 0x8000000000-0xffffffffff]
[    0.405634] pci 0000:00:00.0: [1b36:0008] type 00 class 0x060000
[    0.407312] pci 0000:00:01.0: [1af4:1000] type 00 class 0x020000
[    0.408801] pci 0000:00:01.0: reg 0x10: [io  0x0000-0x001f]
[    0.409984] pci 0000:00:01.0: reg 0x14: [mem 0x00000000-0x00000fff]
[    0.411504] pci 0000:00:01.0: reg 0x20: [mem 0x00000000-0x00003fff 64bit pref]
[    0.413840] pci 0000:00:01.0: reg 0x30: [mem 0x00000000-0x0003ffff pref]
[    0.416196] pci 0000:00:02.0: [1af4:1001] type 00 class 0x010000
[    0.417822] pci 0000:00:02.0: reg 0x10: [io  0x0000-0x007f]
[    0.419063] pci 0000:00:02.0: reg 0x14: [mem 0x00000000-0x00000fff]
[    0.420334] pci 0000:00:02.0: reg 0x20: [mem 0x00000000-0x00003fff 64bit pref]
[    0.423194] pci 0000:00:01.0: BAR 6: assigned [mem 0x10000000-0x1003ffff pref]
[    0.424869] pci 0000:00:01.0: BAR 4: assigned [mem 0x8000000000-0x8000003fff 64bit pref]
[    0.427018] pci 0000:00:02.0: BAR 4: assigned [mem 0x8000004000-0x8000007fff 64bit pref]
[    0.428507] pci 0000:00:01.0: BAR 1: assigned [mem 0x10040000-0x10040fff]
[    0.430560] pci 0000:00:02.0: BAR 1: assigned [mem 0x10041000-0x10041fff]
[    0.432139] pci 0000:00:02.0: BAR 0: assigned [io  0x1000-0x107f]
[    0.433657] pci 0000:00:01.0: BAR 0: assigned [io  0x1080-0x109f]
[    0.439764] EINJ: ACPI disabled.
[    0.444641] virtio-pci 0000:00:01.0: enabling device (0000 -> 0003)
[    0.449017] virtio-pci 0000:00:02.0: enabling device (0000 -> 0003)
[    0.455905] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    0.458373] SuperH (H)SCI(F) driver initialized
[    0.459684] msm_serial: driver initialized
[    0.461407] cacheinfo: Unable to detect cache hierarchy for CPU 0
[    0.465763] loop: module loaded
[    0.468068] virtio_blk virtio1: [vda] 12000000 512-byte logical blocks (6.14 GB/5.72 GiB)
[    0.477848] libphy: Fixed MDIO Bus: probed
[    0.478986] tun: Universal TUN/TAP device driver, 1.6
[    0.482174] thunder_xcv, ver 1.0
[    0.482970] thunder_bgx, ver 1.0
[    0.483806] nicpf, ver 1.0
[    0.484754] hclge is initializing
[    0.485736] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
[    0.487390] hns3: Copyright (c) 2017 Huawei Corporation.
[    0.488827] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    0.490682] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    0.492067] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.6.0-k
[    0.493889] igb: Copyright (c) 2007-2014 Intel Corporation.
[    0.495332] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.4.0-k
[    0.498230] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[    0.499893] sky2: driver version 1.30
[    0.501195] VFIO - User Level meta-driver version: 0.3
[    0.507337] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    0.509403] ehci-pci: EHCI PCI platform driver
[    0.510865] ehci-platform: EHCI generic platform driver
[    0.512295] ehci-orion: EHCI orion driver
[    0.513372] ehci-exynos: EHCI EXYNOS driver
[    0.514497] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    0.515985] ohci-pci: OHCI PCI platform driver
[    0.516978] ohci-platform: OHCI generic platform driver
[    0.518568] ohci-exynos: OHCI EXYNOS driver
[    0.520044] usbcore: registered new interface driver usb-storage
[    0.522710] rtc-pl031 9010000.pl031: registered as rtc0
[    0.524262] i2c /dev entries driver
[    0.527836] sdhci: Secure Digital Host Controller Interface driver
[    0.529490] sdhci: Copyright(c) Pierre Ossman
[    0.530893] Synopsys Designware Multimedia Card Interface Driver
[    0.532651] sdhci-pltfm: SDHCI platform and OF driver helper
[    0.535051] ledtrig-cpu: registered to indicate activity on CPUs
[    0.537058] usbcore: registered new interface driver usbhid
[    0.538898] usbhid: USB HID core driver
[    0.541460] NET: Registered protocol family 17
[    0.542521] 9pnet: Installing 9P2000 support
[    0.543580] Key type dns_resolver registered
[    0.544954] registered taskstats version 1
[    0.546181] Loading compiled-in X.509 certificates
[    0.547737] input: gpio-keys as /devices/platform/gpio-keys/input/input0
[    0.549466] rtc-pl031 9010000.pl031: setting system clock to 2019-08-07T15:40:46 UTC (1565192446)
[    0.553232] ALSA device list:
[    0.554015]   No soundcards found.
[    0.554839] uart-pl011 9000000.pl011: no DMA platform data
[    0.556293] EXT4-fs (vda): mounting ext3 file system using the ext4 subsystem
[    0.564596] EXT4-fs (vda): mounted filesystem with ordered data mode. Opts: (null)
[    0.567288] VFS: Mounted root (ext3 filesystem) readonly on device 254:0.
[    0.569455] devtmpfs: mounted
[    0.571312] Freeing unused kernel memory: 5184K
[    0.572540] Run /sbin/init as init process
[    0.597524] EXT4-fs (vda): re-mounted. Opts: errors=remount-ro
Starting logging: OK
Initializing random number generator... [    0.631818] random: dd: uninitialized urandom read (512 bytes read)
done.
Starting network: udhcpc: started, v1.26.2
udhcpc: sending discover
udhcpc: sending select for 10.0.2.15
udhcpc: lease of 10.0.2.15 obtained, lease time 86400
deleting routers
adding dns 10.0.2.3
OK
Starting sshd: [    0.773922] random: sshd: uninitialized urandom read (32 bytes read)
OK

Welcome to Buildroot
buildroot login: root
Password:
# zcat /proc/config.gz | grep ENDIAN
# CONFIG_CPU_BIG_ENDIAN is not set
# CONFIG_VHOST_CROSS_ENDIAN_LEGACY is not set
# CONFIG_FB_FOREIGN_ENDIAN is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# poweroff
Stopping vtund.
# no process in pidfile '/var/run/vtund*' found; none killed
Stopping sshd: OK
Stopping network: OK
Saving random seed... [   15.010433] random: dd: uninitialized urandom read (512 bytes read)
done.
Stopping logging: OK
umount: devtmpfs busy - remounted read-only
[   15.029155] EXT4-fs (vda): re-mounted. Opts: (null)
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Requesting system poweroff
[   17.035638] reboot: Power down
[

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v3 02/11] kselftest: arm64: adds first test and common utils
From: Cristian Marussi @ 2019-08-07 15:42 UTC (permalink / raw)
  To: linux-kselftest, linux-arm-kernel; +Cc: dave.martin
In-Reply-To: <20190802170300.20662-3-cristian.marussi@arm.com>

Hi

On 02/08/2019 18:02, Cristian Marussi wrote:
> Added some arm64/signal specific boilerplate and utility code to help
> further testcase development.
> 
> A simple testcase and related helpers are also introduced in this commit:
> mangle_pstate_invalid_compat_toggle is a simple mangle testcase which
> messes with the ucontext_t from within the sig_handler, trying to toggle
> PSTATE state bits to switch the system between 32bit/64bit execution state.
> Expects SIGSEGV on test PASS.
> 
> Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
> ---
> A few fixes:
> - test_arm64_signals.sh runner script generation has been reviewed in order to
>   be safe against the .gitignore
> - using kselftest.h officially provided defines for tests' return values
> - removed SAFE_WRITE()/dump_uc()
> - looking for si_code==SEGV_ACCERR on SEGV test cases to better understand if
>   the sigfault had been directly triggered by Kernel
> ---
>  tools/testing/selftests/arm64/Makefile        |   2 +-
>  .../testing/selftests/arm64/signal/.gitignore |   6 +
>  tools/testing/selftests/arm64/signal/Makefile |  88 ++++++
>  tools/testing/selftests/arm64/signal/README   |  59 ++++
>  .../arm64/signal/test_arm64_signals.src_shell |  55 ++++
>  .../selftests/arm64/signal/test_signals.c     |  26 ++
>  .../selftests/arm64/signal/test_signals.h     | 137 +++++++++
>  .../arm64/signal/test_signals_utils.c         | 261 ++++++++++++++++++
>  .../arm64/signal/test_signals_utils.h         |  13 +
>  .../arm64/signal/testcases/.gitignore         |   1 +
>  .../mangle_pstate_invalid_compat_toggle.c     |  25 ++
>  .../arm64/signal/testcases/testcases.c        | 150 ++++++++++
>  .../arm64/signal/testcases/testcases.h        |  83 ++++++
>  13 files changed, 905 insertions(+), 1 deletion(-)
>  create mode 100644 tools/testing/selftests/arm64/signal/.gitignore
>  create mode 100644 tools/testing/selftests/arm64/signal/Makefile
>  create mode 100644 tools/testing/selftests/arm64/signal/README
>  create mode 100755 tools/testing/selftests/arm64/signal/test_arm64_signals.src_shell
>  create mode 100644 tools/testing/selftests/arm64/signal/test_signals.c
>  create mode 100644 tools/testing/selftests/arm64/signal/test_signals.h
>  create mode 100644 tools/testing/selftests/arm64/signal/test_signals_utils.c
>  create mode 100644 tools/testing/selftests/arm64/signal/test_signals_utils.h
>  create mode 100644 tools/testing/selftests/arm64/signal/testcases/.gitignore
>  create mode 100644 tools/testing/selftests/arm64/signal/testcases/mangle_pstate_invalid_compat_toggle.c
>  create mode 100644 tools/testing/selftests/arm64/signal/testcases/testcases.c
>  create mode 100644 tools/testing/selftests/arm64/signal/testcases/testcases.h
> 

I discovered an additional issue with this patch while building
some additional SVE related arm64/signal testcases (ofr a different patch series),
which is related to the logic of the helper get_header() that is flawed under some
specific conditions (not exposed by the test-cases included in this series).

A fix like the one below will go into V4, once reviews have settled.

diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c
index a59785092e1f..0727b3987bbd 100644
--- a/tools/testing/selftests/arm64/signal/testcases/testcases.c
+++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c
@@ -10,9 +10,16 @@ struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
                return found;
 
        do {
+               /*
+                * account for the fact that:
+                * - we could be in search of the terminator itself
+                * - a terminator should anyway terminate the loop
+                */
                if (head->magic == magic) {
                        found = head;
                        break;
+               } else if (!head->magic) {
+                       break;
                }
                offs += head->size;
                head = GET_RESV_NEXT_HEAD(head);

Cheers

Cristian

> diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
> index 03a0d4f71218..af59dc74e0dc 100644
> --- a/tools/testing/selftests/arm64/Makefile
> +++ b/tools/testing/selftests/arm64/Makefile
> @@ -6,7 +6,7 @@ ARCH ?= $(shell uname -m)
>  ARCH := $(shell echo $(ARCH) | sed -e s/aarch64/arm64/)
>  
>  ifeq ("x$(ARCH)", "xarm64")
> -SUBDIRS :=
> +SUBDIRS := signal
>  else
>  SUBDIRS :=
>  endif
> diff --git a/tools/testing/selftests/arm64/signal/.gitignore b/tools/testing/selftests/arm64/signal/.gitignore
> new file mode 100644
> index 000000000000..434f65c15f03
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/.gitignore
> @@ -0,0 +1,6 @@
> +# Helper script's internal testcases list (TPROGS) is regenerated
> +# each time by Makefile on standalone (non KSFT driven) runs.
> +# Committing such list creates a dependency between testcases
> +# patches such that they are no more easily revertable. Just ignore.
> +test_arm64_signals.src_shell
> +test_arm64_signals.sh
> diff --git a/tools/testing/selftests/arm64/signal/Makefile b/tools/testing/selftests/arm64/signal/Makefile
> new file mode 100644
> index 000000000000..8c8d08be4b0d
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/Makefile
> @@ -0,0 +1,88 @@
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (C) 2019 ARM Limited
> +
> +# Supports also standalone invokation out of KSFT-tree
> +# Compile standalone and run on your device with:
> +#
> +#  $ make -C tools/testing/selftests/arm64/signal INSTALL_PATH=<your-dir> install
> +#
> +# Run standalone on device with:
> +#
> +#  $ <your-device-instdir>/test_arm64_signals.sh [-k|-v]
> +#
> +# If INSTALL_PATH= is NOT provided it will default to ./install
> +
> +# A proper top_srcdir is needed both by KSFT(lib.mk)
> +# and standalone builds
> +top_srcdir = ../../../../..
> +
> +CFLAGS += -std=gnu99 -I. -I$(top_srcdir)/tools/testing/selftests/
> +SRCS := $(filter-out testcases/testcases.c,$(wildcard testcases/*.c))
> +PROGS := $(patsubst %.c,%,$(SRCS))
> +
> +# Guessing as best as we can where the Kernel headers
> +# could have been installed depending on ENV config and
> +# type of invocation.
> +ifeq ($(KBUILD_OUTPUT),)
> +khdr_dir = $(top_srcdir)/usr/include
> +else
> +ifeq (0,$(MAKELEVEL))
> +khdr_dir = $(KBUILD_OUTPUT)/usr/include
> +else
> +# the KSFT preferred location when KBUILD_OUTPUT is set
> +khdr_dir = $(KBUILD_OUTPUT)/kselftest/usr/include
> +endif
> +endif
> +
> +CFLAGS += -I$(khdr_dir)
> +
> +# Standalone run
> +ifeq (0,$(MAKELEVEL))
> +CC := $(CROSS_COMPILE)gcc
> +RUNNER_SRC = test_arm64_signals.src_shell
> +RUNNER = test_arm64_signals.sh
> +INSTALL_PATH ?= install/
> +
> +all: $(RUNNER)
> +
> +$(RUNNER): $(PROGS)
> +	cp $(RUNNER_SRC) $(RUNNER)
> +	sed -i -e 's#PROGS=.*#PROGS="$(PROGS)"#' $@
> +
> +install: all
> +	mkdir -p $(INSTALL_PATH)/testcases
> +	cp $(PROGS) $(INSTALL_PATH)/testcases
> +	cp $(RUNNER) $(INSTALL_PATH)/
> +
> +.PHONY clean:
> +	rm -f $(PROGS)
> +# KSFT run
> +else
> +# Generated binaries to be installed by top KSFT script
> +TEST_GEN_PROGS := $(notdir $(PROGS))
> +
> +# Get Kernel headers installed and use them.
> +KSFT_KHDR_INSTALL := 1
> +
> +# This include mk will also mangle the TEST_GEN_PROGS list
> +# to account for any OUTPUT target-dirs optionally provided
> +# by the toplevel makefile
> +include ../../lib.mk
> +
> +$(TEST_GEN_PROGS): $(PROGS)
> +	cp $(PROGS) $(OUTPUT)/
> +
> +clean:
> +	$(CLEAN)
> +	rm -f $(PROGS)
> +endif
> +
> +# Common test-unit targets to build common-layout test-cases executables
> +# Needs secondary expansion to properly include the testcase c-file in pre-reqs
> +.SECONDEXPANSION:
> +$(PROGS): test_signals.c test_signals_utils.c testcases/testcases.c $$@.c test_signals.h test_signals_utils.h testcases/testcases.h
> +	@if [ ! -d $(khdr_dir) ]; then \
> +		echo -n "\n!!! WARNING: $(khdr_dir) NOT FOUND."; \
> +		echo "===>  Are you sure Kernel Headers have been installed properly ?\n"; \
> +	fi
> +	$(CC) $(CFLAGS) $^ -o $@
> diff --git a/tools/testing/selftests/arm64/signal/README b/tools/testing/selftests/arm64/signal/README
> new file mode 100644
> index 000000000000..53f005f7910a
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/README
> @@ -0,0 +1,59 @@
> +KSelfTest arm64/signal/
> +=======================
> +
> +Signals Tests
> ++++++++++++++
> +
> +- Tests are built around a common main compilation unit: such shared main
> +  enforces a standard sequence of operations needed to perform a single
> +  signal-test (setup/trigger/run/result/cleanup)
> +
> +- The above mentioned ops are configurable on a test-by-test basis: each test
> +  is described (and configured) using the descriptor signals.h::struct tdescr
> +
> +- Each signal testcase is compiled into its own executable: a separate
> +  executable is used for each test since many tests complete successfully
> +  by receiving some kind of fatal signal from the Kernel, so it's safer
> +  to run each test unit in its own standalone process, so as to start each
> +  test from a clean slate.
> +
> +- New tests can be simply defined in testcases/ dir providing a proper struct
> +  tdescr overriding all the defaults we wish to change (as of now providing a
> +  custom run method is mandatory though)
> +
> +- Signals' test-cases hereafter defined belong currently to two
> +  principal families:
> +
> +  - 'mangle_' tests: a real signal (SIGUSR1) is raised and used as a trigger
> +    and then the test case code messes-up with the sigframe ucontext_t from
> +    inside the sighandler itself.
> +
> +  - 'fake_sigreturn_' tests: a brand new custom artificial sigframe structure
> +    is placed on the stack and a sigreturn syscall is called to simulate a
> +    real signal return. This kind of tests does not use a trigger usually and
> +    they are just fired using some simple included assembly trampoline code.
> +
> + - Most of these tests are successfully passing if the process gets killed by
> +   some fatal signal: usually SIGSEGV or SIGBUS. Since while writing this
> +   kind of tests it is extremely easy in fact to end-up injecting other
> +   unrelated SEGV bugs in the testcases, it becomes extremely tricky to
> +   be really sure that the tests are really addressing what they are meant
> +   to address and they are not instead falling apart due to unplanned bugs
> +   in the test code.
> +   In order to alleviate the misery of the life of such test-developer, a few
> +   helpers are provided:
> +
> +   - a couple of ASSERT_BAD/GOOD_CONTEXT() macros to easily parse a ucontext_t
> +     and verify if it is indeed GOOD or BAD (depending on what we were
> +     expecting), using the same logic/perspective as in the arm64 Kernel signals
> +     routines.
> +
> +   - a sanity mechanism to be used in 'fake_sigreturn_'-alike tests: enabled by
> +     default it takes care to verify that the test-execution had at least
> +     successfully progressed up to the stage of triggering the fake sigreturn
> +     call.
> +
> +  In both cases test results are expected in terms of:
> +   - some fatal signal sent by the Kernel to the test process
> +  or
> +  - analyzing some final regs state
> diff --git a/tools/testing/selftests/arm64/signal/test_arm64_signals.src_shell b/tools/testing/selftests/arm64/signal/test_arm64_signals.src_shell
> new file mode 100755
> index 000000000000..163e941e2997
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/test_arm64_signals.src_shell
> @@ -0,0 +1,55 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (C) 2019 ARM Limited
> +
> +ret=0
> +keep_on_fail=0
> +err_out="2> /dev/null"
> +
> +usage() {
> +	echo "Usage: `basename $0` [-v] [-k]"
> +	exit 1
> +}
> +
> +# avoiding getopt to avoid compatibility issues on targets
> +# with limited resources
> +while [ $# -gt 0 ]
> +do
> +	case $1 in
> +		"-k")
> +			keep_on_fail=1
> +			;;
> +		"-v")
> +			err_out=
> +			;;
> +		*)
> +			usage
> +			;;
> +	esac
> +	shift
> +done
> +
> +TPROGS=
> +
> +tot=$(echo $TPROGS | wc -w)
> +
> +# Tests are expected in testcases/ subdir inside the installation path
> +workdir="`dirname $0 2>/dev/null`"
> +[ -n $workdir ] && cd $workdir
> +
> +passed=0
> +run=0
> +for test in $TPROGS
> +do
> +	run=$((run + 1))
> +	eval ./$test $err_out
> +	if [ $? != 0 ]; then
> +		[ $keep_on_fail = 0 ] && echo "===>>> FAILED:: $test <<<===" && ret=1 && break
> +	else
> +		passed=$((passed + 1))
> +	fi
> +done
> +
> +echo "==>> PASSED: $passed/$run on $tot available tests."
> +
> +exit $ret
> diff --git a/tools/testing/selftests/arm64/signal/test_signals.c b/tools/testing/selftests/arm64/signal/test_signals.c
> new file mode 100644
> index 000000000000..3447d7011aec
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/test_signals.c
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2019 ARM Limited */
> +
> +#include <kselftest.h>
> +
> +#include "test_signals.h"
> +#include "test_signals_utils.h"
> +
> +struct tdescr *current;
> +extern struct tdescr tde;
> +
> +int main(int argc, char *argv[])
> +{
> +	current = &tde;
> +
> +	ksft_print_msg("%s :: %s - SIG_TRIG:%d  SIG_OK:%d -- current:%p\n",
> +		       current->name, current->descr, current->sig_trig,
> +		       current->sig_ok, current);
> +	if (test_setup(current)) {
> +		if (test_run(current))
> +			test_result(current);
> +		test_cleanup(current);
> +	}
> +
> +	return current->pass ? KSFT_PASS : KSFT_FAIL;
> +}
> diff --git a/tools/testing/selftests/arm64/signal/test_signals.h b/tools/testing/selftests/arm64/signal/test_signals.h
> new file mode 100644
> index 000000000000..85db3ac44b32
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/test_signals.h
> @@ -0,0 +1,137 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2019 ARM Limited */
> +
> +#ifndef __TEST_SIGNALS_H__
> +#define __TEST_SIGNALS_H__
> +
> +#include <assert.h>
> +#include <stdbool.h>
> +#include <signal.h>
> +#include <ucontext.h>
> +#include <stdint.h>
> +
> +/*
> + * Using ARCH specific and sanitized Kernel headers installed by KSFT
> + * framework since we asked for it by setting flag KSFT_KHDR_INSTALL
> + * in our Makefile.
> + */
> +#include <asm/ptrace.h>
> +#include <asm/hwcap.h>
> +
> +/* pasted from include/linux/stringify.h */
> +#define __stringify_1(x...)	#x
> +#define __stringify(x...)	__stringify_1(x)
> +
> +/*
> + * Reads a sysreg using the, possibly provided, S3_ encoding in order to
> + * avoid inject any dependency on the used toolchain regarding possibly
> + * still unsupported ARMv8 extensions.
> + *
> + * Using a standard mnemonic here to indicate the specific sysreg (like SSBS)
> + * would introduce a compile-time dependency on possibly unsupported ARMv8
> + * Extensions: you could end-up failing to build the test depending on the
> + * available toolchain.
> + * This is undesirable since some tests, even if specifically targeted at some
> + * ARMv8 Extensions, can be plausibly run even on hardware lacking the above
> + * optional ARM features. (SSBS bit preservation is an example: Kernel handles
> + * it transparently not caring at all about the effective set of supported
> + * features).
> + * On the other side we will expect to observe different behaviours if the
> + * feature is supported or not: usually getting a SIGILL when trying to use
> + * unsupported features. For this reason we have anyway in place some
> + * preliminary run-time checks about the cpu effectively supported features.
> + *
> + * This helper macro is meant to be used for regs readable at EL0, BUT some
> + * EL1 sysregs are indeed readable too through MRS emulation Kernel-mechanism
> + * if the required reg is included in the supported encoding space:
> + *
> + *  Documentation/arm64/cpu-feature-regsiters.txt
> + *
> + *  "The infrastructure emulates only the following system register space:
> + *   	Op0=3, Op1=0, CRn=0, CRm=0,4,5,6,7
> + */
> +#define get_regval(regname, out) \
> +	asm volatile("mrs %0, " __stringify(regname) : "=r" (out) :: "memory")
> +
> +/* Regs encoding and masks naming copied in from sysreg.h */
> +#define SYS_ID_AA64MMFR1_EL1	S3_0_C0_C7_1	/* MRS Emulated */
> +#define SYS_ID_AA64MMFR2_EL1	S3_0_C0_C7_2	/* MRS Emulated */
> +#define ID_AA64MMFR1_PAN_SHIFT	20
> +#define ID_AA64MMFR2_UAO_SHIFT	4
> +
> +/* Local Helpers */
> +#define IS_PAN_SUPPORTED(val) \
> +	(!!((val) & (0xfUL << ID_AA64MMFR1_PAN_SHIFT)))
> +#define IS_UAO_SUPPORTED(val) \
> +	(!!((val) & (0xfUL << ID_AA64MMFR2_UAO_SHIFT)))
> +
> +#define S3_MRS_SSBS_SYSREG		S3_3_C4_C2_6	/* EL0 supported */
> +
> +/*
> + * Feature flags used in tdescr.feats_required to specify
> + * any feature by the test
> + */
> +enum {
> +	FSSBS_BIT,
> +	FPAN_BIT,
> +	FUAO_BIT,
> +	FMAX_END
> +};
> +
> +#define FEAT_SSBS		(1UL << FSSBS_BIT)
> +#define FEAT_PAN		(1UL << FPAN_BIT)
> +#define FEAT_UAO		(1UL << FUAO_BIT)
> +
> +/*
> + * A descriptor used to describe and configure a test case.
> + * Fields with a non-trivial meaning are described inline in the following.
> + */
> +struct tdescr {
> +	/* KEEP THIS FIELD FIRST for easier lookup from assembly */
> +	void		*token;
> +	/* when disabled token based sanity checking is skipped in handler */
> +	bool		sanity_disabled;
> +	/* just a name for the test-case; manadatory field */
> +	char		*name;
> +	char		*descr;
> +	unsigned long	feats_required;
> +	/* bitmask of effectively supported feats: populated at run-time */
> +	unsigned long	feats_supported;
> +	bool		feats_ok;
> +	bool		initialized;
> +	unsigned int	minsigstksz;
> +	/* signum used as a test trigger. Zero if no trigger-signal is used */
> +	int		sig_trig;
> +	/*
> +	 * signum considered as a successful test completion.
> +	 * Zero when no signal is expected on success
> +	 */
> +	int		sig_ok;
> +	/* signum expected on unsupported CPU features. */
> +	int		sig_unsupp;
> +	/* a timeout in second for test completion */
> +	unsigned int	timeout;
> +	bool		triggered;
> +	bool		pass;
> +	/* optional sa_flags for the installed handler */
> +	int		sa_flags;
> +	ucontext_t	saved_uc;
> +
> +	/* a setup function to be called before test starts */
> +	int (*setup)(struct tdescr *td);
> +	void (*cleanup)(struct tdescr *td);
> +
> +	/* an optional function to be used as a trigger for test starting */
> +	int (*trigger)(struct tdescr *td);
> +	/*
> +	 * the actual test-core: invoked differently depending on the
> +	 * presence of the trigger function above; this is mandatory
> +	 */
> +	int (*run)(struct tdescr *td, siginfo_t *si, ucontext_t *uc);
> +
> +	/* an optional function for custom results' processing */
> +	void (*check_result)(struct tdescr *td);
> +
> +	void *priv;
> +};
> +#endif
> diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.c b/tools/testing/selftests/arm64/signal/test_signals_utils.c
> new file mode 100644
> index 000000000000..ac0055f6340b
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.c
> @@ -0,0 +1,261 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2019 ARM Limited */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <signal.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <assert.h>
> +#include <sys/auxv.h>
> +#include <linux/auxvec.h>
> +#include <ucontext.h>
> +
> +#include "test_signals.h"
> +#include "test_signals_utils.h"
> +#include "testcases/testcases.h"
> +
> +extern struct tdescr *current;
> +
> +static char *feats_store[FMAX_END] = {
> +	"SSBS",
> +	"PAN",
> +	"UAO"
> +};
> +
> +#define MAX_FEATS_SZ	128
> +static inline char *feats_to_string(unsigned long feats)
> +{
> +	static char feats_string[MAX_FEATS_SZ];
> +
> +	for (int i = 0; i < FMAX_END && feats_store[i][0]; i++) {
> +		if (feats & 1UL << i)
> +			snprintf(feats_string, MAX_FEATS_SZ - 1, "%s %s ",
> +				 feats_string, feats_store[i]);
> +	}
> +
> +	return feats_string;
> +}
> +
> +static void unblock_signal(int signum)
> +{
> +	sigset_t sset;
> +
> +	sigemptyset(&sset);
> +	sigaddset(&sset, signum);
> +	sigprocmask(SIG_UNBLOCK, &sset, NULL);
> +}
> +
> +static void default_result(struct tdescr *td, bool force_exit)
> +{
> +	if (td->pass)
> +		fprintf(stderr, "==>> completed. PASS(1)\n");
> +	else
> +		fprintf(stdout, "==>> completed. FAIL(0)\n");
> +	if (force_exit)
> +		exit(td->pass ? EXIT_SUCCESS : EXIT_FAILURE);
> +}
> +
> +static inline bool are_feats_ok(struct tdescr *td)
> +{
> +	return td ? td->feats_required == td->feats_supported : 0;
> +}
> +
> +static void default_handler(int signum, siginfo_t *si, void *uc)
> +{
> +	if (current->sig_trig && signum == current->sig_trig) {
> +		fprintf(stderr, "Handling SIG_TRIG\n");
> +		current->triggered = 1;
> +		/* ->run was asserted NON-NULL in test_setup() already */
> +		current->run(current, si, uc);
> +	} else if (signum == SIGILL && !current->initialized) {
> +		/*
> +		 * A SIGILL here while still not initialized means we failed
> +		 * even to asses the existence of features during init
> +		 */
> +		fprintf(stdout,
> +			"Got SIGILL test_init. Marking ALL features UNSUPPORTED.\n");
> +		current->feats_supported = 0;
> +	} else if (current->sig_ok && signum == current->sig_ok) {
> +		/* it's a bug in the test code when this assert fail */
> +		assert(!current->sig_trig || current->triggered);
> +		fprintf(stderr,
> +			"SIG_OK -- SP:%p  si_addr@:0x%p  si_code:%d  token@:0x%p  offset:%ld\n",
> +			((ucontext_t *)uc)->uc_mcontext.sp,
> +			si->si_addr, si->si_code, current->token,
> +			current->token - si->si_addr);
> +		/*
> +		 * fake_sigreturn tests, which have sanity_enabled=1, set, at
> +		 * the very last time, the token field to the SP address used
> +		 * to place the fake sigframe: so token==0 means we never made
> +		 * it to the end, segfaulting well-before, and the test is
> +		 * possibly broken.
> +		 */
> +		if (!current->sanity_disabled && !current->token) {
> +			fprintf(stdout,
> +				"current->token ZEROED...test is probably broken!\n");
> +			assert(0);
> +		}
> +		/*
> +		 * Trying to narrow down the SEGV to the ones generated by
> +		 * Kernel itself via arm64_notify_segfault()
> +		 */
> +		if (current->sig_ok == SIGSEGV && si->si_code != SEGV_ACCERR) {
> +			fprintf(stdout,
> +				"si_code != SEGV_ACCERR...test is probably broken!\n");
> +			assert(0);
> +		}
> +		fprintf(stderr, "Handling SIG_OK\n");
> +		current->pass = 1;
> +		/*
> +		 * Some tests can lead to SEGV loops: in such a case we want
> +		 * to terminate immediately exiting straight away
> +		 */
> +		default_result(current, 1);
> +	} else {
> +		if (signum == current->sig_unsupp && !are_feats_ok(current)) {
> +			fprintf(stderr, "-- RX SIG_UNSUPP on unsupported feature...OK\n");
> +			current->pass = 1;
> +		} else if (signum == SIGALRM && current->timeout) {
> +			fprintf(stderr, "-- Timeout !\n");
> +		} else {
> +			fprintf(stderr,
> +				"-- RX UNEXPECTED SIGNAL: %d\n", signum);
> +		}
> +		default_result(current, 1);
> +	}
> +}
> +
> +static int default_setup(struct tdescr *td)
> +{
> +	struct sigaction sa;
> +
> +	sa.sa_sigaction = default_handler;
> +	sa.sa_flags = SA_SIGINFO;
> +	if (td->sa_flags)
> +		sa.sa_flags |= td->sa_flags;
> +	sigemptyset(&sa.sa_mask);
> +	/* uncatchable signals naturally skipped ... */
> +	for (int sig = 1; sig < 32; sig++)
> +		sigaction(sig, &sa, NULL);
> +	/*
> +	 * RT Signals default disposition is Term but they cannot be
> +	 * generated by the Kernel in response to our tests; so just catch
> +	 * them all and report them as UNEXPECTED signals.
> +	 */
> +	for (int sig = SIGRTMIN; sig <= SIGRTMAX; sig++)
> +		sigaction(sig, &sa, NULL);
> +
> +	/* just in case...unblock explicitly all we need */
> +	if (td->sig_trig)
> +		unblock_signal(td->sig_trig);
> +	if (td->sig_ok)
> +		unblock_signal(td->sig_ok);
> +	if (td->sig_unsupp)
> +		unblock_signal(td->sig_unsupp);
> +
> +	if (td->timeout) {
> +		unblock_signal(SIGALRM);
> +		alarm(td->timeout);
> +	}
> +	fprintf(stderr, "Registered handlers for all signals.\n");
> +
> +	return 1;
> +}
> +
> +static inline int default_trigger(struct tdescr *td)
> +{
> +	return !raise(td->sig_trig);
> +}
> +
> +static int test_init(struct tdescr *td)
> +{
> +	td->minsigstksz = getauxval(AT_MINSIGSTKSZ);
> +	if (!td->minsigstksz)
> +		td->minsigstksz = MINSIGSTKSZ;
> +	fprintf(stderr, "Detected MINSTKSIGSZ:%d\n", td->minsigstksz);
> +
> +	if (td->feats_required) {
> +		bool feats_ok = false;
> +		td->feats_supported = 0;
> +		/*
> +		 * Checking for CPU required features using both the
> +		 * auxval and the arm64 MRS Emulation to read sysregs.
> +		 */
> +		if (getauxval(AT_HWCAP) & HWCAP_CPUID) {
> +			uint64_t val = 0;
> +
> +			if (td->feats_required & FEAT_SSBS) {
> +				/* Uses HWCAP to check capability */
> +				if (getauxval(AT_HWCAP) & HWCAP_SSBS)
> +					td->feats_supported |= FEAT_SSBS;
> +			}
> +			if (td->feats_required & FEAT_PAN) {
> +				/* Uses MRS emulation to check capability */
> +				get_regval(SYS_ID_AA64MMFR1_EL1, val);
> +				if (IS_PAN_SUPPORTED(val))
> +					td->feats_supported |= FEAT_PAN;
> +			}
> +			if (td->feats_required & FEAT_UAO) {
> +				/* Uses MRS emulation to check capability */
> +				get_regval(SYS_ID_AA64MMFR2_EL1 , val);
> +				if (IS_UAO_SUPPORTED(val))
> +					td->feats_supported |= FEAT_UAO;
> +			}
> +		} else {
> +			fprintf(stderr,
> +				"HWCAP_CPUID NOT available. Mark ALL feats UNSUPPORTED.\n");
> +		}
> +		feats_ok = are_feats_ok(td);
> +		fprintf(stderr,
> +			"Required Features: [%s] %ssupported\n",
> +			feats_ok ? feats_to_string(td->feats_supported) :
> +		        feats_to_string(td->feats_required ^ td->feats_supported),
> +			!feats_ok ? "NOT " : "");
> +	}
> +
> +	td->initialized = 1;
> +	return 1;
> +}
> +
> +int test_setup(struct tdescr *td)
> +{
> +	/* assert core invariants symptom of a rotten testcase */
> +	assert(current);
> +	assert(td);
> +	assert(td->name);
> +	assert(td->run);
> +
> +	if (!test_init(td))
> +		return 0;
> +
> +	if (td->setup)
> +		return td->setup(td);
> +	else
> +		return default_setup(td);
> +}
> +
> +int test_run(struct tdescr *td)
> +{
> +	if (td->sig_trig) {
> +		if (td->trigger)
> +			return td->trigger(td);
> +		else
> +			return default_trigger(td);
> +	} else {
> +		return td->run(td, NULL, NULL);
> +	}
> +}
> +
> +void test_result(struct tdescr *td)
> +{
> +	if (td->check_result)
> +		td->check_result(td);
> +	default_result(td, 0);
> +}
> +
> +void test_cleanup(struct tdescr *td)
> +{
> +	if (td->cleanup)
> +		td->cleanup(td);
> +}
> diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.h b/tools/testing/selftests/arm64/signal/test_signals_utils.h
> new file mode 100644
> index 000000000000..8658d1a7d4b9
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2019 ARM Limited */
> +
> +#ifndef __TEST_SIGNALS_UTILS_H__
> +#define __TEST_SIGNALS_UTILS_H__
> +
> +#include "test_signals.h"
> +
> +int test_setup(struct tdescr *td);
> +void test_cleanup(struct tdescr *td);
> +int test_run(struct tdescr *td);
> +void test_result(struct tdescr *td);
> +#endif
> diff --git a/tools/testing/selftests/arm64/signal/testcases/.gitignore b/tools/testing/selftests/arm64/signal/testcases/.gitignore
> new file mode 100644
> index 000000000000..8651272e3cfc
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/testcases/.gitignore
> @@ -0,0 +1 @@
> +mangle_pstate_invalid_compat_toggle
> diff --git a/tools/testing/selftests/arm64/signal/testcases/mangle_pstate_invalid_compat_toggle.c b/tools/testing/selftests/arm64/signal/testcases/mangle_pstate_invalid_compat_toggle.c
> new file mode 100644
> index 000000000000..971193e7501b
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/testcases/mangle_pstate_invalid_compat_toggle.c
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2019 ARM Limited */
> +
> +#include "test_signals_utils.h"
> +#include "testcases.h"
> +
> +static int mangle_invalid_pstate_run(struct tdescr *td, siginfo_t *si,
> +				     ucontext_t *uc)
> +{
> +	ASSERT_GOOD_CONTEXT(uc);
> +
> +	/* This config should trigger a SIGSEGV by Kernel */
> +	uc->uc_mcontext.pstate ^= PSR_MODE32_BIT;
> +
> +	return 1;
> +}
> +
> +struct tdescr tde = {
> +		.sanity_disabled = true,
> +		.name = "MANGLE_PSTATE_INVALID_STATE_TOGGLE",
> +		.descr = "Mangling uc_mcontext with INVALID STATE_TOGGLE",
> +		.sig_trig = SIGUSR1,
> +		.sig_ok = SIGSEGV,
> +		.run = mangle_invalid_pstate_run,
> +};
> diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c
> new file mode 100644
> index 000000000000..a59785092e1f
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c
> @@ -0,0 +1,150 @@
> +#include "testcases.h"
> +
> +struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
> +				size_t resv_sz, size_t *offset)
> +{
> +	size_t offs = 0;
> +	struct _aarch64_ctx *found = NULL;
> +
> +	if (!head || resv_sz < HDR_SZ)
> +		return found;
> +
> +	do {
> +		if (head->magic == magic) {
> +			found = head;
> +			break;
> +		}
> +		offs += head->size;
> +		head = GET_RESV_NEXT_HEAD(head);
> +	} while (offs < resv_sz - HDR_SZ);
> +
> +	if (offset)
> +		*offset = offs;
> +
> +	return found;
> +}
> +
> +bool validate_extra_context(struct extra_context *extra, char **err)
> +{
> +	struct _aarch64_ctx *term;
> +
> +	if (!extra || !err)
> +		return false;
> +
> +	fprintf(stderr, "Validating EXTRA...\n");
> +	term = GET_RESV_NEXT_HEAD(extra);
> +	if (!term || term->magic || term->size) {
> +		*err = "UN-Terminated EXTRA context";
> +		return false;
> +	}
> +	if (extra->datap & 0x0fUL)
> +		*err = "Extra DATAP misaligned";
> +	else if (extra->size & 0x0fUL)
> +		*err = "Extra SIZE misaligned";
> +	else if (extra->datap != (uint64_t)term + sizeof(*term))
> +		*err = "Extra DATAP misplaced (not contiguos)";
> +	if (*err)
> +		return false;
> +
> +	return true;
> +}
> +
> +bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
> +{
> +	bool terminated = false;
> +	size_t offs = 0;
> +	int flags = 0;
> +	struct extra_context *extra = NULL;
> +	struct _aarch64_ctx *head =
> +		(struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
> +
> +	if (!err)
> +		return false;
> +	/* Walk till the end terminator verifying __reserved contents */
> +	while (head && !terminated && offs < resv_sz) {
> +		if ((uint64_t)head & 0x0fUL) {
> +			*err = "Misaligned HEAD";
> +			return false;
> +		}
> +
> +		switch (head->magic) {
> +			case 0:
> +				if (head->size)
> +					*err = "Bad size for MAGIC0";
> +				else
> +					terminated = true;
> +				break;
> +			case FPSIMD_MAGIC:
> +				if (flags & FPSIMD_CTX)
> +					*err = "Multiple FPSIMD_MAGIC";
> +				else if (head->size !=
> +					 sizeof(struct fpsimd_context))
> +					*err = "Bad size for fpsimd_context";
> +				flags |= FPSIMD_CTX;
> +				break;
> +			case ESR_MAGIC:
> +				if (head->size != sizeof(struct esr_context))
> +					fprintf(stderr,
> +						"Bad size for esr_context is not an error...just ignore.\n");
> +				break;
> +			case SVE_MAGIC:
> +				if (flags & SVE_CTX)
> +					*err = "Multiple SVE_MAGIC";
> +				else if (head->size !=
> +					 sizeof(struct sve_context))
> +					*err = "Bad size for sve_context";
> +				flags |= SVE_CTX;
> +				break;
> +			case EXTRA_MAGIC:
> +				if (flags & EXTRA_CTX)
> +					*err = "Multiple EXTRA_MAGIC";
> +				else if (head->size !=
> +					 sizeof(struct extra_context))
> +					*err = "Bad size for extra_context";
> +				flags |= EXTRA_CTX;
> +				extra = (struct extra_context *)head;
> +				break;
> +			case KSFT_BAD_MAGIC:
> +				/*
> +				 * This is a BAD magic header defined
> +				 * artificially by a testcase and surely
> +				 * unknown to the Kernel parse_user_sigframe().
> +				 * It MUST cause a Kernel induced SEGV
> +				 */
> +				*err = "BAD MAGIC !";
> +				break;
> +			default:
> +				/*
> +				 * A still unknown Magic: potentially freshly added
> +				 * to the Kernel code and still unknown to the
> +				 * tests.
> +				 */
> +				fprintf(stdout,
> +					"SKIP Unknown MAGIC: 0x%X - Is KSFT arm64/signal up to date ?\n",
> +					head->magic);
> +				break;
> +		}
> +
> +		if (*err)
> +			return false;
> +
> +		offs += head->size;
> +		if (resv_sz - offs < sizeof(*head)) {
> +			*err = "HEAD Overrun";
> +			return false;
> +		}
> +
> +		if (flags & EXTRA_CTX)
> +			if (!validate_extra_context(extra, err))
> +				return false;
> +
> +		head = GET_RESV_NEXT_HEAD(head);
> +	}
> +
> +	if (terminated && !(flags & FPSIMD_CTX)) {
> +		*err = "Missing FPSIMD";
> +		return false;
> +	}
> +
> +	return true;
> +}
> diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.h b/tools/testing/selftests/arm64/signal/testcases/testcases.h
> new file mode 100644
> index 000000000000..624717c71b1d
> --- /dev/null
> +++ b/tools/testing/selftests/arm64/signal/testcases/testcases.h
> @@ -0,0 +1,83 @@
> +#ifndef __TESTCASES_H__
> +#define __TESTCASES_H__
> +
> +#include <stdio.h>
> +#include <stdbool.h>
> +#include <stdint.h>
> +#include <unistd.h>
> +#include <ucontext.h>
> +#include <assert.h>
> +
> +/* Architecture specific sigframe definitions */
> +#include <asm/sigcontext.h>
> +
> +#define FPSIMD_CTX	(1 << 0)
> +#define SVE_CTX		(1 << 1)
> +#define EXTRA_CTX	(1 << 2)
> +
> +#define KSFT_BAD_MAGIC	0xdeadbeef
> +
> +#define HDR_SZ \
> +	sizeof(struct _aarch64_ctx)
> +
> +#define GET_SF_RESV_HEAD(sf) \
> +	(struct _aarch64_ctx *)(&(sf).uc.uc_mcontext.__reserved)
> +
> +#define GET_SF_RESV_SIZE(sf) \
> +	sizeof((sf).uc.uc_mcontext.__reserved)
> +
> +#define GET_UCP_RESV_SIZE(ucp) \
> +	sizeof((ucp)->uc_mcontext.__reserved)
> +
> +#define ASSERT_BAD_CONTEXT(uc) do {					\
> +	char *err = NULL;						\
> +	assert(!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err));\
> +	if (err)							\
> +		fprintf(stderr,						\
> +			"Using badly built context - ERR: %s\n", err);	\
> +} while(0)
> +
> +#define ASSERT_GOOD_CONTEXT(uc) do {					 \
> +	char *err = NULL;						 \
> +	if (!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err)) {	 \
> +		if (err)						 \
> +			fprintf(stderr,					 \
> +				"Detected BAD context - ERR: %s\n", err);\
> +		assert(0);						 \
> +	} else {							 \
> +		fprintf(stderr, "uc context validated.\n");		 \
> +	}								 \
> +} while(0)
> +
> +/* head->size accounts both for payload and header _aarch64_ctx size ! */
> +#define GET_RESV_NEXT_HEAD(h) \
> +	(struct _aarch64_ctx *)((char *)(h) + (h)->size)
> +
> +struct fake_sigframe {
> +	siginfo_t	info;
> +	ucontext_t	uc;
> +};
> +
> +
> +bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err);
> +
> +bool validate_extra_context(struct extra_context *extra, char **err);
> +
> +struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
> +				size_t resv_sz, size_t *offset);
> +
> +static inline struct _aarch64_ctx *get_terminator(struct _aarch64_ctx *head,
> +						  size_t resv_sz,
> +						  size_t *offset)
> +{
> +	return get_header(head, 0, resv_sz, offset);
> +}
> +
> +static inline void write_terminator_record(struct _aarch64_ctx *tail)
> +{
> +	if (tail) {
> +		tail->magic = 0;
> +		tail->size = 0;
> +	}
> +}
> +#endif
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* Re: [PATCH v6 3/3] thermal: cpu_cooling: Migrate to using the EM framework
From: Quentin Perret @ 2019-08-07 15:42 UTC (permalink / raw)
  To: edubezval, rui.zhang, javi.merino, viresh.kumar, amit.kachhap,
	rjw, catalin.marinas, will, daniel.lezcano, lkp
  Cc: linux-pm, linux-kernel, mka, ionela.voinescu, dietmar.eggemann,
	linux-arm-kernel
In-Reply-To: <20190801124643.17112-4-quentin.perret@arm.com>

Hi all,

On Thursday 01 Aug 2019 at 13:46:43 (+0100), Quentin Perret wrote:
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 9966364a6deb..340853a3ca48 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -144,6 +144,7 @@ config THERMAL_GOV_USER_SPACE
>  
>  config THERMAL_GOV_POWER_ALLOCATOR
>  	bool "Power allocator thermal governor"
> +	depends on ENERGY_MODEL
>  	help
>  	  Enable this to manage platform thermals by dynamically
>  	  allocating and limiting power to devices.

FYI, the kbuild bot just reported a randconfig build issue with this.
THERMAL_DEFAULT_GOV_POWER_ALLOCATOR 'select' THERMAL_GOV_POWER_ALLOCATOR
unconditionally. And I just learned 'select' will force the option ON
and totally ignore its dependencies. That is, we can end up with IPA
force-compiled in, and no PM_EM, which is broken.

So I guess the simplest fix is to do 'select ENERGY_MODEL' in this
patch, instead of depending on it.

I'll send a v7 with this fixed shortly.

Thanks,
Quentin

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] arm64: KVM: hyp: debug-sr: Mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2019-08-07 15:40 UTC (permalink / raw)
  To: Marc Zyngier, James Morse, Julien Thierry, Suzuki K Poulose,
	Catalin Marinas, Will Deacon
  Cc: kvmarm, linux-arm-kernel, linux-kernel
In-Reply-To: <b0b04024-9568-7b51-1bef-7030dd66f727@kernel.org>



On 8/7/19 10:11 AM, Marc Zyngier wrote:

> 
> Already fixed (together with all the other KVM/arm warnings/bugs), and
> pull request sent to Paolo.
> 

Awesome. :)

Thanks, Marc.
--
Gustavo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v8 00/14] Rockchip ISP1 Driver
From: Sakari Ailus @ 2019-08-07 15:37 UTC (permalink / raw)
  To: Helen Koike
  Cc: devicetree, eddie.cai.linux, kernel, heiko, jacob2.chen,
	jeffy.chen, zyc, linux-kernel, tfiga, linux-rockchip,
	hans.verkuil, laurent.pinchart, zhengsq, mchehab, ezequiel,
	linux-arm-kernel, linux-media
In-Reply-To: <20190730184256.30338-1-helen.koike@collabora.com>

On Tue, Jul 30, 2019 at 03:42:42PM -0300, Helen Koike wrote:
> Hello,
> 
> I'm re-sending a new version of ISP(Camera) v4l2 driver for rockchip
> rk3399 SoC.
> 
> I didn't change much from the last version, just applying the
> suggestions made in the previous one.
> 
> This patchset is also available at:
> https://gitlab.collabora.com/koike/linux/tree/rockchip/isp/v8
> 
> Libcamera patched to work with this version:
> https://gitlab.collabora.com/koike/libcamera
> (also sent to the mailing list)
> 
> I tested on the rockpi 4 with a rpi v1.3 sensor and also with the
> Scarlet Chromebook.

Could you also post media-ctl -p printout e.g. as a reply to the cover
letter?

Thanks.

-- 
Sakari Ailus
sakari.ailus@linux.intel.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v8 09/14] media: rkisp1: add rockchip isp1 core driver
From: Sakari Ailus @ 2019-08-07 15:36 UTC (permalink / raw)
  To: Helen Koike
  Cc: devicetree, eddie.cai.linux, kernel, heiko, jacob2.chen,
	jeffy.chen, zyc, linux-kernel, tfiga, linux-rockchip, Allon Huang,
	Jacob Chen, hans.verkuil, laurent.pinchart, zhengsq, mchehab,
	ezequiel, linux-arm-kernel, linux-media
In-Reply-To: <20190730184256.30338-10-helen.koike@collabora.com>

Hi Helen,

On Tue, Jul 30, 2019 at 03:42:51PM -0300, Helen Koike wrote:

...

> +static int rkisp1_fwnode_parse(struct device *dev,
> +			       struct v4l2_fwnode_endpoint *vep,
> +			       struct v4l2_async_subdev *asd)
> +{
> +	struct sensor_async_subdev *s_asd =
> +			container_of(asd, struct sensor_async_subdev, asd);
> +
> +	if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
> +		dev_err(dev, "Only CSI2 bus type is currently supported\n");
> +		return -EINVAL;
> +	}
> +
> +	if (vep->base.port != 0) {
> +		dev_err(dev, "The ISP has only port 0\n");
> +		return -EINVAL;
> +	}
> +
> +	s_asd->mbus.type = vep->bus_type;
> +	s_asd->mbus.flags = vep->bus.mipi_csi2.flags;
> +	s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
> +
> +	switch (vep->bus.mipi_csi2.num_data_lanes) {
> +	case 1:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_1_LANE;
> +		break;
> +	case 2:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_2_LANE;
> +		break;
> +	case 3:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_3_LANE;
> +		break;
> +	case 4:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_4_LANE;
> +		break;

Could you use struct v4l2_fwnode_endpoint directly? The mbus config is a
legacy struct from bygone times and I'd like to avoid using it in new
drivers.

> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
> +	.bound = subdev_notifier_bound,
> +	.unbind = subdev_notifier_unbind,
> +	.complete = subdev_notifier_complete,
> +};
> +
> +static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
> +{
> +	struct v4l2_async_notifier *ntf = &isp_dev->notifier;
> +	struct device *dev = isp_dev->dev;
> +	int ret;
> +
> +	v4l2_async_notifier_init(ntf);
> +
> +	ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> +		dev, ntf, sizeof(struct sensor_async_subdev), 0,
> +		rkisp1_fwnode_parse);

I know these functions aren't old but there's a better alternative. See
e.g. isp_parse_of_endpoints in drivers/media/platform/omap3isp/isp.c or
cio2_parse_firmware in drivers/media/pci/intel/ipu3/ipu3-cio2.c.

> +	if (ret < 0)
> +		return ret;
> +
> +	if (list_empty(&ntf->asd_list))
> +		return -ENODEV;	/* no endpoint */
> +
> +	ntf->ops = &subdev_notifier_ops;
> +
> +	return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
> +}

-- 
Sakari Ailus
sakari.ailus@linux.intel.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [Sound-open-firmware] [PATCH v2 3/5] ASoC: SOF: Add DT DSP device support
From: Daniel Baluta @ 2019-08-07 15:29 UTC (permalink / raw)
  To: Pierre-Louis Bossart
  Cc: Mark Rutland, Aisheng Dong, Peng Fan, Fabio Estevam, Anson Huang,
	Devicetree List, Daniel Baluta, S.j. Wang, Marco Felsch,
	Linux Kernel Mailing List, Paul Olaru, Rob Herring, dl-linux-imx,
	Pengutronix Kernel Team, Leonard Crestez, Shawn Guo,
	linux-arm-kernel, sound-open-firmware
In-Reply-To: <d85909d6-c7cb-c64b-dfa9-6cee6c0da2cb@linux.intel.com>

On Tue, Jul 23, 2019 at 6:19 PM Pierre-Louis Bossart
<pierre-louis.bossart@linux.intel.com> wrote:
>
>
> > diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
> > index 61b97fc55bb2..2aa3a1cdf60c 100644
> > --- a/sound/soc/sof/Kconfig
> > +++ b/sound/soc/sof/Kconfig
> > @@ -36,6 +36,15 @@ config SND_SOC_SOF_ACPI
> >         Say Y if you need this option
> >         If unsure select "N".
> >
> > +config SND_SOC_SOF_DT
> > +     tristate "SOF DT enumeration support"
> > +     select SND_SOC_SOF
> > +     select SND_SOC_SOF_OPTIONS
> > +     help
> > +       This adds support for Device Tree enumeration. This option is
> > +       required to enable i.MX8 devices.
> > +       Say Y if you need this option. If unsure select "N".
> > +
>
> [snip]
>
> > diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig
> > index fff64a9970f0..fa35994a79c4 100644
> > --- a/sound/soc/sof/imx/Kconfig
> > +++ b/sound/soc/sof/imx/Kconfig
> > @@ -12,6 +12,7 @@ if SND_SOC_SOF_IMX_TOPLEVEL
> >
> >   config SND_SOC_SOF_IMX8
> >       tristate "SOF support for i.MX8"
> > +     select SND_SOC_SOF_DT
>
> This looks upside down. You should select SOF_DT first then include the
> NXP stuff.

One more thing: So this should be 'depends on SND_SOC_SOF_DT' right?

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] arm64: Disable big endian builds with clang
From: Mark Brown @ 2019-08-07 15:29 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Tri Vo, Catalin Marinas, Nick Desaulniers, clang-built-linux,
	Matt Hart, Nathan Chancellor, Will Deacon, linux-arm-kernel
In-Reply-To: <20190807135618.GF54191@lakrids.cambridge.arm.com>


[-- Attachment #1.1: Type: text/plain, Size: 1904 bytes --]

On Wed, Aug 07, 2019 at 02:56:19PM +0100, Mark Rutland wrote:
> On Wed, Aug 07, 2019 at 02:05:27PM +0100, Mark Brown wrote:

> > As far as I know this has been broken for as long as we tried building
> > and booting big endian kernels in clang.  The compile works fine, it's
> > just that the resulting binary doesn't seem to be working so well.

> I've just had a go, and it works for me. Log below from a BE busybox,
> but I also have a BE buildroot filesystem working.

Copying Matt who can actually look at the jobs getting submitted.  The
rootfs we're using should be:

	https://storage.kernelci.org/images/rootfs/buildroot/arm64be/

> From your log, it looks like the kernel is trying to launch init via
> binfmt_misc, using binfmt-464c. It could be that the file is corrupted
> somehow, or something's going wrong with binfmt. I haven't delved into
> that.

You can see the exact image being used in the reports I linked:

	https://storage.kernelci.org/next/master/next-20190730/arm64/defconfig+CONFIG_CPU_BIG_ENDIAN=y/clang-8/Image

> Are you using the right filesystem (and is the kernel definitely
> identifying itself as BE in the Image header flags)?

I'm assured that we're using the same rootfs as the GCC BE builds, sadly
neither of the labs that has boards configured to allow BE boots gives
enough access for me to verify that personally.

> This could be a dynamic loader issue -- my busybox is statically linked,
> and I'm not sure about my buildroot filesystem.

> This could be platform-specific; I'm booting under a KVM/QEMU VM on
> ThunderX2, using virtio-block for storage.

It's failing on every single platform we're trying, that's not as many
as it should be but it's still a bunch of physical platforms and like I
say the variable is the compiler.  A platform issue that only manifests
in the handover to userspace on multiple boards doesn't seem like the
most likely avenue.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [Sound-open-firmware] [PATCH v2 3/5] ASoC: SOF: Add DT DSP device support
From: Daniel Baluta @ 2019-08-07 15:28 UTC (permalink / raw)
  To: Pierre-Louis Bossart
  Cc: Mark Rutland, Aisheng Dong, Peng Fan, Fabio Estevam, Anson Huang,
	Devicetree List, Daniel Baluta, S.j. Wang, Marco Felsch,
	Linux Kernel Mailing List, Paul Olaru, Rob Herring, dl-linux-imx,
	Pengutronix Kernel Team, Leonard Crestez, Shawn Guo,
	linux-arm-kernel, sound-open-firmware
In-Reply-To: <85b4a2c4-761e-bdcf-f05e-2fb16c06f11e@linux.intel.com>

On Wed, Aug 7, 2019 at 6:22 PM Pierre-Louis Bossart
<pierre-louis.bossart@linux.intel.com> wrote:
>
>
> >>>> +static int sof_dt_probe(struct platform_device *pdev)
> >>>> +{
> >>>> +     struct device *dev = &pdev->dev;
> >>>> +     const struct sof_dev_desc *desc;
> >>>> +     /*TODO: create a generic snd_soc_xxx_mach */
> >>>> +     struct snd_soc_acpi_mach *mach;
> >>>
> >>> I wonder if you really need to use the same structures. For Intel we get
> >>> absolutely zero info from the firmware so rely on an ACPI codec ID as a
> >>> key to find information on which firmware and topology to use, and which
> >>> machine driver to load. You could have all this information in a DT blob?
> >>
> >> Yes. I see your point. I will still need to make a generic structure for
> >> snd_soc_acpi_mach so that everyone can use sof_nocodec_setup function.
> >>
> >> Maybe something like this:
> >>
> >> struct snd_soc_mach {
> >>    union {
> >>    struct snd_soc_acpi_mach acpi_mach;
> >>    struct snd_soc_of_mach of_mach;
> >>    }
> >> };
> >>
> >> and then change the prototype of sof_nocodec_setup.
> >
> > Hi Pierre,
> >
> > I fixed all the comments except the one above. Replacing snd_soc_acpi_mach
> > with a generic snd_soc_mach is not trivial task.
> >
> > I wonder if it is acceptable to get the initial patches as they are
> > now and later switch to
> > generic ACPI/OF abstraction.
> >
> > Asking this because for the moment on the i.MX side I have only
> > implemented no codec
> > version and we don't probe any of the machine drivers we have.
> >
> > So, there is this only one member of snd_soc_acpi_mach that imx
> > version is making use of:
> >
> >    mach->drv_name = "sof-nocodec";
> >
> > That's all.
> >
> > I think the change as it is now is very clean and non-intrusive. Later
> > we will get options to
> > read firmware name and stuff from DT.
> >
> > Anyhow, I don't think we can get rid of snd_dev_desc structure on
> > i.MX. This will be used
> > to store the information read from DT:
> >
> > static struct sof_dev_desc sof_of_imx8qxp_desc = {
> > »       .default_fw_path = "imx/sof",
> > »       .default_tplg_path = "imx/sof-tplg",
> > »       .nocodec_fw_filename = "sof-imx8.ri",
> > »       .nocodec_tplg_filename = "sof-imx8-nocodec.tplg",
> > »       .ops = &sof_imx8_ops,
> > };
> >
> > For the moment we will only use the default values.
>
> Yes, that's fine for now. If you don't have a real machine driver then
> there's nothing urgent to change.
>
> Is the new version on GitHub?

Not yet, will push it today and ping you.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v8 09/14] media: rkisp1: add rockchip isp1 core driver
From: Sakari Ailus @ 2019-08-07 15:27 UTC (permalink / raw)
  To: Helen Koike
  Cc: devicetree, eddie.cai.linux, kernel, heiko, jacob2.chen,
	jeffy.chen, zyc, linux-kernel, tfiga, linux-rockchip, Allon Huang,
	Jacob Chen, hans.verkuil, laurent.pinchart, zhengsq, mchehab,
	ezequiel, linux-arm-kernel, linux-media
In-Reply-To: <20190730184256.30338-10-helen.koike@collabora.com>

Hi Helen,

On Tue, Jul 30, 2019 at 03:42:51PM -0300, Helen Koike wrote:
> From: Jacob Chen <jacob2.chen@rock-chips.com>
> 
> Add the core driver for rockchip isp1.
> 
> Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
> Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>
> Signed-off-by: Yichong Zhong <zyc@rock-chips.com>
> Signed-off-by: Jacob Chen <cc@rock-chips.com>
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
> Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
> Signed-off-by: Tomasz Figa <tfiga@chromium.org>
> [fixed compilation and run time errors regarding new v4l2 async API]
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> [Add missing module device table]
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> [update for upstream]
> Signed-off-by: Helen Koike <helen.koike@collabora.com>
> 
> ---
> 
> Changes in v8: None
> Changes in v7:
> - VIDEO_ROCKCHIP_ISP1 selects VIDEOBUF2_VMALLOC
> - add PHY_ROCKCHIP_DPHY as a dependency for VIDEO_ROCKCHIP_ISP1
> - Fix compilation and runtime errors due to bitrotting
> The code has bit-rotten since March 2018, fix compilation errors.
> The new V4L2 async notifier API requires notifiers to be initialized by
> a call to v4l2_async_notifier_init() before being used, do so.
> - Add missing module device table
> - use clk_bulk framework
> - add missing notifiers cleanups
> - s/strlcpy/strscpy
> - normalize bus_info name
> - fix s_stream error path, stream_cnt wans't being decremented properly
> - use devm_platform_ioremap_resource() helper
> - s/deice/device
> - redesign: remove mipi/csi subdevice, sensors connect directly to the
> isp subdevice in the media topology now.
> - remove "saved_state" member from rkisp1_stream struct
> - Reverse the order of MIs
> - Simplify MI interrupt handling
> Rather than adding unnecessary indirection, just use stream index to
> handle MI interrupt enable/disable/clear, since the stream index matches
> the order of bits now, thanks to previous patch. While at it, remove
> some dead code.
> - code styling and checkpatch fixes
> 
>  drivers/media/platform/Kconfig                |  12 +
>  drivers/media/platform/Makefile               |   1 +
>  drivers/media/platform/rockchip/isp1/Makefile |   7 +
>  drivers/media/platform/rockchip/isp1/common.h | 101 +++
>  drivers/media/platform/rockchip/isp1/dev.c    | 675 ++++++++++++++++++
>  drivers/media/platform/rockchip/isp1/dev.h    |  97 +++
>  6 files changed, 893 insertions(+)
>  create mode 100644 drivers/media/platform/rockchip/isp1/Makefile
>  create mode 100644 drivers/media/platform/rockchip/isp1/common.h
>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.c
>  create mode 100644 drivers/media/platform/rockchip/isp1/dev.h
> 
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index 89555f9a813f..e0e98937c565 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -106,6 +106,18 @@ config VIDEO_QCOM_CAMSS
>  	select VIDEOBUF2_DMA_SG
>  	select V4L2_FWNODE
>  
> +config VIDEO_ROCKCHIP_ISP1
> +	tristate "Rockchip Image Signal Processing v1 Unit driver"
> +	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
> +	depends on ARCH_ROCKCHIP || COMPILE_TEST
> +	select VIDEOBUF2_DMA_CONTIG
> +	select VIDEOBUF2_VMALLOC
> +	select V4L2_FWNODE
> +	select PHY_ROCKCHIP_DPHY
> +	default n
> +	---help---
> +	  Support for ISP1 on the rockchip SoC.
> +
>  config VIDEO_S3C_CAMIF
>  	tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
>  	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
> index 7cbbd925124c..f9fcf8e7c513 100644
> --- a/drivers/media/platform/Makefile
> +++ b/drivers/media/platform/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_RENESAS_FDP1)	+= rcar_fdp1.o
>  obj-$(CONFIG_VIDEO_RENESAS_JPU)		+= rcar_jpu.o
>  obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1/
>  
> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1)	+= rockchip/isp1/
>  obj-$(CONFIG_VIDEO_ROCKCHIP_RGA)	+= rockchip/rga/
>  
>  obj-y	+= omap/
> diff --git a/drivers/media/platform/rockchip/isp1/Makefile b/drivers/media/platform/rockchip/isp1/Makefile
> new file mode 100644
> index 000000000000..72706e80fc8b
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/Makefile
> @@ -0,0 +1,7 @@
> +obj-$(CONFIG_VIDEO_ROCKCHIP_ISP1) += 	rockchip-isp1.o
> +rockchip-isp1-objs 	   += 	rkisp1.o \
> +				dev.o \
> +				regs.o \
> +				isp_stats.o \
> +				isp_params.o \
> +				capture.o
> diff --git a/drivers/media/platform/rockchip/isp1/common.h b/drivers/media/platform/rockchip/isp1/common.h
> new file mode 100644
> index 000000000000..606ce2793546
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/common.h
> @@ -0,0 +1,101 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#ifndef _RKISP1_COMMON_H
> +#define _RKISP1_COMMON_H
> +
> +#include <linux/mutex.h>
> +#include <media/media-device.h>
> +#include <media/media-entity.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-device.h>
> +#include <media/videobuf2-v4l2.h>
> +
> +#define RKISP1_DEFAULT_WIDTH		800
> +#define RKISP1_DEFAULT_HEIGHT		600
> +
> +#define RKISP1_MAX_STREAM		2
> +#define RKISP1_STREAM_MP		0
> +#define RKISP1_STREAM_SP		1
> +
> +#define RKISP1_PLANE_Y			0
> +#define RKISP1_PLANE_CB			1
> +#define RKISP1_PLANE_CR			2
> +
> +enum rkisp1_sd_type {
> +	RKISP1_SD_SENSOR,
> +	RKISP1_SD_PHY_CSI,
> +	RKISP1_SD_VCM,
> +	RKISP1_SD_FLASH,
> +	RKISP1_SD_MAX,
> +};

I wonder if this is a leftover from the driver development time. Same goes
for the subdevs field in struct rkisp1_device.

> +
> +/* One structure per video node */
> +struct rkisp1_vdev_node {
> +	struct vb2_queue buf_queue;
> +	/* vfd lock */
> +	struct mutex vlock;
> +	struct video_device vdev;
> +	struct media_pad pad;
> +};
> +
> +enum rkisp1_fmt_pix_type {
> +	FMT_YUV,
> +	FMT_RGB,
> +	FMT_BAYER,
> +	FMT_JPEG,
> +	FMT_MAX
> +};
> +
> +enum rkisp1_fmt_raw_pat_type {
> +	RAW_RGGB = 0,
> +	RAW_GRBG,
> +	RAW_GBRG,
> +	RAW_BGGR,
> +};
> +
> +struct rkisp1_buffer {
> +	struct vb2_v4l2_buffer vb;
> +	struct list_head queue;
> +	union {
> +		u32 buff_addr[VIDEO_MAX_PLANES];
> +		void *vaddr[VIDEO_MAX_PLANES];
> +	};
> +};
> +
> +struct rkisp1_dummy_buffer {
> +	void *vaddr;
> +	dma_addr_t dma_addr;
> +	u32 size;
> +};
> +
> +extern int rkisp1_debug;
> +
> +static inline
> +struct rkisp1_vdev_node *vdev_to_node(struct video_device *vdev)
> +{
> +	return container_of(vdev, struct rkisp1_vdev_node, vdev);
> +}
> +
> +static inline struct rkisp1_vdev_node *queue_to_node(struct vb2_queue *q)
> +{
> +	return container_of(q, struct rkisp1_vdev_node, buf_queue);
> +}
> +
> +static inline struct rkisp1_buffer *to_rkisp1_buffer(struct vb2_v4l2_buffer *vb)
> +{
> +	return container_of(vb, struct rkisp1_buffer, vb);
> +}
> +
> +static inline struct vb2_queue *to_vb2_queue(struct file *file)
> +{
> +	struct rkisp1_vdev_node *vnode = video_drvdata(file);
> +
> +	return &vnode->buf_queue;
> +}
> +
> +#endif /* _RKISP1_COMMON_H */
> diff --git a/drivers/media/platform/rockchip/isp1/dev.c b/drivers/media/platform/rockchip/isp1/dev.c
> new file mode 100644
> index 000000000000..2b4a67e1a3b5
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/dev.c
> @@ -0,0 +1,675 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_graph.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/pinctrl/consumer.h>
> +#include <linux/phy/phy.h>
> +#include <linux/phy/phy-mipi-dphy.h>
> +
> +#include "common.h"
> +#include "regs.h"
> +
> +struct isp_match_data {
> +	const char * const *clks;
> +	int size;

unsigned int

> +};
> +
> +struct sensor_async_subdev {
> +	struct v4l2_async_subdev asd;
> +	struct v4l2_mbus_config mbus;
> +	unsigned int lanes;
> +};
> +
> +int rkisp1_debug;
> +module_param_named(debug, rkisp1_debug, int, 0644);
> +MODULE_PARM_DESC(debug, "Debug level (0-1)");

Have you thought of using dynamic debug instead?

> +
> +/**************************** pipeline operations******************************/
> +
> +static int __isp_pipeline_prepare(struct rkisp1_pipeline *p,
> +				  struct media_entity *me)
> +{
> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> +	struct v4l2_subdev *sd;
> +	unsigned int i;
> +
> +	p->num_subdevs = 0;
> +	memset(p->subdevs, 0, sizeof(p->subdevs));
> +
> +	while (1) {
> +		struct media_pad *pad = NULL;
> +
> +		/* Find remote source pad */
> +		for (i = 0; i < me->num_pads; i++) {
> +			struct media_pad *spad = &me->pads[i];
> +
> +			if (!(spad->flags & MEDIA_PAD_FL_SINK))
> +				continue;
> +			pad = media_entity_remote_pad(spad);
> +			if (pad)
> +				break;
> +		}
> +
> +		if (!pad)
> +			break;
> +
> +		sd = media_entity_to_v4l2_subdev(pad->entity);
> +		if (sd != &dev->isp_sdev.sd)
> +			p->subdevs[p->num_subdevs++] = sd;

How do you make sure you don't overrun the array?

Instead, I'd avoid maintaining the array in the first place --- the same
information is available from the MC framework data structures --- see e.g.
the omap3isp driver.

> +
> +		me = &sd->entity;
> +		if (me->num_pads == 1)
> +			break;
> +	}
> +	return 0;
> +}
> +
> +static int __subdev_set_power(struct v4l2_subdev *sd, int on)
> +{
> +	int ret;
> +
> +	if (!sd)
> +		return -ENXIO;
> +
> +	ret = v4l2_subdev_call(sd, core, s_power, on);
> +
> +	return ret != -ENOIOCTLCMD ? ret : 0;
> +}
> +
> +static int __isp_pipeline_s_power(struct rkisp1_pipeline *p, bool on)

Could you instead use v4l2_pipeline_pm_use()?

> +{
> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> +	int i, ret;
> +
> +	if (on) {
> +		__subdev_set_power(&dev->isp_sdev.sd, true);
> +
> +		for (i = p->num_subdevs - 1; i >= 0; --i) {
> +			ret = __subdev_set_power(p->subdevs[i], true);
> +			if (ret < 0 && ret != -ENXIO)
> +				goto err_power_off;
> +		}
> +	} else {
> +		for (i = 0; i < p->num_subdevs; ++i)
> +			__subdev_set_power(p->subdevs[i], false);
> +
> +		__subdev_set_power(&dev->isp_sdev.sd, false);
> +	}
> +
> +	return 0;
> +
> +err_power_off:
> +	for (++i; i < p->num_subdevs; ++i)
> +		__subdev_set_power(p->subdevs[i], false);
> +	__subdev_set_power(&dev->isp_sdev.sd, true);
> +	return ret;
> +}
> +
> +static int rkisp1_pipeline_open(struct rkisp1_pipeline *p,
> +				struct media_entity *me,
> +				bool prepare)
> +{
> +	int ret;
> +
> +	if (WARN_ON(!p || !me))
> +		return -EINVAL;
> +	if (atomic_inc_return(&p->power_cnt) > 1)
> +		return 0;
> +
> +	/* go through media graphic and get subdevs */
> +	if (prepare)
> +		__isp_pipeline_prepare(p, me);
> +
> +	if (!p->num_subdevs)
> +		return -EINVAL;
> +
> +	ret = __isp_pipeline_s_power(p, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int rkisp1_pipeline_close(struct rkisp1_pipeline *p)
> +{
> +	int ret;
> +
> +	if (atomic_dec_return(&p->power_cnt) > 0)
> +		return 0;
> +	ret = __isp_pipeline_s_power(p, 0);
> +
> +	return ret == -ENXIO ? 0 : ret;
> +}
> +
> +/*
> + * stream-on order: isp_subdev, mipi dphy, sensor
> + * stream-off order: mipi dphy, sensor, isp_subdev
> + */
> +static int rkisp1_pipeline_set_stream(struct rkisp1_pipeline *p, bool on)
> +{
> +	struct rkisp1_device *dev = container_of(p, struct rkisp1_device, pipe);
> +	int i, ret;
> +
> +	if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
> +	    (!on && atomic_dec_return(&p->stream_cnt) > 0))
> +		return 0;
> +
> +	if (on) {
> +		ret = v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream,
> +				       true);
> +		if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
> +			v4l2_err(&dev->v4l2_dev,
> +				 "s_stream failed on subdevice %s (%d)\n",
> +				 dev->isp_sdev.sd.name,
> +				 ret);
> +			atomic_dec(&p->stream_cnt);
> +			return ret;
> +		}
> +	}
> +
> +	/* phy -> sensor */
> +	for (i = 0; i < p->num_subdevs; ++i) {
> +		ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
> +		if (on && ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
> +			goto err_stream_off;

You should stop after the first external sub-device.

It seems even the omap3isp driver doesn't do that. It's not easy to spot
such issues indeed.

> +	}
> +
> +	if (!on)
> +		v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> +
> +	return 0;
> +
> +err_stream_off:
> +	for (--i; i >= 0; --i)
> +		v4l2_subdev_call(p->subdevs[i], video, s_stream, false);
> +	v4l2_subdev_call(&dev->isp_sdev.sd, video, s_stream, false);
> +	atomic_dec(&p->stream_cnt);
> +	return ret;
> +}
> +
> +/***************************** media controller *******************************/
> +/* See http://opensource.rock-chips.com/wiki_Rockchip-isp1 for Topology */

The host appears to be down, or there's a routing problem. Unless this is
fixed, having such a URL here doesn't do much good. :-I

> +
> +static int rkisp1_create_links(struct rkisp1_device *dev)
> +{
> +	struct media_entity *source, *sink;
> +	struct rkisp1_sensor *sensor;
> +	unsigned int flags, pad;
> +	int ret;
> +
> +	/* sensor links(or mipi-phy) */
> +	list_for_each_entry(sensor, &dev->sensors, list) {
> +		for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
> +			if (sensor->sd->entity.pads[pad].flags &
> +				MEDIA_PAD_FL_SOURCE)
> +				break;

Could you use media_entity_get_fwnode_pad() instead?

> +
> +		if (pad == sensor->sd->entity.num_pads) {
> +			dev_err(dev->dev,
> +				"failed to find src pad for %s\n",
> +				sensor->sd->name);
> +
> +			return -ENXIO;
> +		}
> +
> +		ret = media_create_pad_link(
> +				&sensor->sd->entity, pad,
> +				&dev->isp_sdev.sd.entity,
> +				RKISP1_ISP_PAD_SINK,
> +				list_is_first(&sensor->list, &dev->sensors) ?
> +				MEDIA_LNK_FL_ENABLED : 0);
> +		if (ret) {
> +			dev_err(dev->dev,
> +				"failed to create link for %s\n",
> +				sensor->sd->name);
> +			return ret;
> +		}
> +	}
> +
> +	/* params links */
> +	source = &dev->params_vdev.vnode.vdev.entity;
> +	sink = &dev->isp_sdev.sd.entity;
> +	flags = MEDIA_LNK_FL_ENABLED;
> +	ret = media_create_pad_link(source, 0, sink,
> +				       RKISP1_ISP_PAD_SINK_PARAMS, flags);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* create isp internal links */
> +	/* SP links */
> +	source = &dev->isp_sdev.sd.entity;
> +	sink = &dev->stream[RKISP1_STREAM_SP].vnode.vdev.entity;
> +	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> +				       sink, 0, flags);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* MP links */
> +	source = &dev->isp_sdev.sd.entity;
> +	sink = &dev->stream[RKISP1_STREAM_MP].vnode.vdev.entity;
> +	ret = media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_PATH,
> +				       sink, 0, flags);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* 3A stats links */
> +	source = &dev->isp_sdev.sd.entity;
> +	sink = &dev->stats_vdev.vnode.vdev.entity;
> +	return media_create_pad_link(source, RKISP1_ISP_PAD_SOURCE_STATS,
> +					sink, 0, flags);

Indentation. Same for the calls to the same function above.

> +}
> +
> +static int subdev_notifier_bound(struct v4l2_async_notifier *notifier,
> +				 struct v4l2_subdev *sd,
> +				 struct v4l2_async_subdev *asd)
> +{
> +	struct rkisp1_device *isp_dev = container_of(notifier,
> +						     struct rkisp1_device,
> +						     notifier);
> +	struct sensor_async_subdev *s_asd = container_of(asd,
> +					struct sensor_async_subdev, asd);
> +	struct rkisp1_sensor *sensor;
> +
> +	sensor = devm_kzalloc(isp_dev->dev, sizeof(*sensor), GFP_KERNEL);
> +	if (!sensor)
> +		return -ENOMEM;
> +
> +	sensor->lanes = s_asd->lanes;
> +	sensor->mbus = s_asd->mbus;
> +	sensor->sd = sd;
> +	sensor->dphy = devm_phy_get(isp_dev->dev, "dphy");
> +	if (IS_ERR(sensor->dphy)) {
> +		if (PTR_ERR(sensor->dphy) != -EPROBE_DEFER)
> +			dev_err(isp_dev->dev, "Couldn't get the MIPI D-PHY\n");
> +		return PTR_ERR(sensor->dphy);
> +	}
> +	phy_init(sensor->dphy);
> +
> +	list_add(&sensor->list, &isp_dev->sensors);

In general, maintaining the information on the external subdevs on your own
adds complexity to the driver. You can get the information when you need it
from the data structures maintained by MC (see e.g. the omap3isp driver for
examples).

> +
> +	return 0;
> +}
> +
> +static struct rkisp1_sensor *sd_to_sensor(struct rkisp1_device *dev,
> +					  struct v4l2_subdev *sd)
> +{
> +	struct rkisp1_sensor *sensor;
> +
> +	list_for_each_entry(sensor, &dev->sensors, list)
> +		if (sensor->sd == sd)
> +			return sensor;
> +
> +	return NULL;
> +}
> +
> +static void subdev_notifier_unbind(struct v4l2_async_notifier *notifier,
> +				   struct v4l2_subdev *sd,
> +				   struct v4l2_async_subdev *asd)
> +{
> +	struct rkisp1_device *isp_dev = container_of(notifier,
> +						     struct rkisp1_device,
> +						     notifier);
> +	struct rkisp1_sensor *sensor = sd_to_sensor(isp_dev, sd);
> +
> +	/* TODO: check if a lock is required here */
> +	list_del(&sensor->list);
> +
> +	phy_exit(sensor->dphy);
> +}
> +
> +static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
> +{
> +	struct rkisp1_device *dev = container_of(notifier, struct rkisp1_device,
> +						 notifier);
> +	int ret;
> +
> +	mutex_lock(&dev->media_dev.graph_mutex);
> +	ret = rkisp1_create_links(dev);
> +	if (ret < 0)
> +		goto unlock;
> +	ret = v4l2_device_register_subdev_nodes(&dev->v4l2_dev);
> +	if (ret < 0)
> +		goto unlock;
> +
> +	v4l2_info(&dev->v4l2_dev, "Async subdev notifier completed\n");
> +
> +unlock:
> +	mutex_unlock(&dev->media_dev.graph_mutex);
> +	return ret;
> +}
> +
> +static int rkisp1_fwnode_parse(struct device *dev,
> +			       struct v4l2_fwnode_endpoint *vep,
> +			       struct v4l2_async_subdev *asd)
> +{
> +	struct sensor_async_subdev *s_asd =
> +			container_of(asd, struct sensor_async_subdev, asd);
> +
> +	if (vep->bus_type != V4L2_MBUS_CSI2_DPHY) {
> +		dev_err(dev, "Only CSI2 bus type is currently supported\n");
> +		return -EINVAL;
> +	}
> +
> +	if (vep->base.port != 0) {
> +		dev_err(dev, "The ISP has only port 0\n");
> +		return -EINVAL;
> +	}
> +
> +	s_asd->mbus.type = vep->bus_type;
> +	s_asd->mbus.flags = vep->bus.mipi_csi2.flags;
> +	s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
> +
> +	switch (vep->bus.mipi_csi2.num_data_lanes) {
> +	case 1:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_1_LANE;
> +		break;
> +	case 2:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_2_LANE;
> +		break;
> +	case 3:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_3_LANE;
> +		break;
> +	case 4:
> +		s_asd->mbus.flags |= V4L2_MBUS_CSI2_4_LANE;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_async_notifier_operations subdev_notifier_ops = {
> +	.bound = subdev_notifier_bound,
> +	.unbind = subdev_notifier_unbind,
> +	.complete = subdev_notifier_complete,
> +};
> +
> +static int isp_subdev_notifier(struct rkisp1_device *isp_dev)
> +{
> +	struct v4l2_async_notifier *ntf = &isp_dev->notifier;
> +	struct device *dev = isp_dev->dev;
> +	int ret;
> +
> +	v4l2_async_notifier_init(ntf);
> +
> +	ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
> +		dev, ntf, sizeof(struct sensor_async_subdev), 0,
> +		rkisp1_fwnode_parse);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (list_empty(&ntf->asd_list))
> +		return -ENODEV;	/* no endpoint */
> +
> +	ntf->ops = &subdev_notifier_ops;
> +
> +	return v4l2_async_notifier_register(&isp_dev->v4l2_dev, ntf);
> +}
> +
> +/***************************** platform device *******************************/
> +
> +static int rkisp1_register_platform_subdevs(struct rkisp1_device *dev)
> +{
> +	int ret;
> +
> +	ret = rkisp1_register_isp_subdev(dev, &dev->v4l2_dev);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = rkisp1_register_stream_vdevs(dev);
> +	if (ret < 0)
> +		goto err_unreg_isp_subdev;
> +
> +	ret = rkisp1_register_stats_vdev(&dev->stats_vdev, &dev->v4l2_dev, dev);
> +	if (ret < 0)
> +		goto err_unreg_stream_vdev;
> +
> +	ret = rkisp1_register_params_vdev(&dev->params_vdev, &dev->v4l2_dev,
> +					  dev);
> +	if (ret < 0)
> +		goto err_unreg_stats_vdev;
> +
> +	ret = isp_subdev_notifier(dev);
> +	if (ret < 0) {
> +		v4l2_err(&dev->v4l2_dev,
> +			 "Failed to register subdev notifier(%d)\n", ret);
> +		goto err_unreg_params_vdev;
> +	}
> +
> +	return 0;
> +err_unreg_params_vdev:
> +	rkisp1_unregister_params_vdev(&dev->params_vdev);
> +err_unreg_stats_vdev:
> +	rkisp1_unregister_stats_vdev(&dev->stats_vdev);
> +err_unreg_stream_vdev:
> +	rkisp1_unregister_stream_vdevs(dev);
> +err_unreg_isp_subdev:
> +	rkisp1_unregister_isp_subdev(dev);
> +	return ret;
> +}
> +
> +static const char * const rk3399_isp_clks[] = {
> +	"clk_isp",
> +	"aclk_isp",
> +	"hclk_isp",
> +	"aclk_isp_wrap",
> +	"hclk_isp_wrap",
> +};
> +
> +static const char * const rk3288_isp_clks[] = {
> +	"clk_isp",
> +	"aclk_isp",
> +	"hclk_isp",
> +	"pclk_isp_in",
> +	"sclk_isp_jpe",
> +};
> +
> +static const struct isp_match_data rk3288_isp_clk_data = {
> +	.clks = rk3288_isp_clks,
> +	.size = ARRAY_SIZE(rk3288_isp_clks),
> +};
> +
> +static const struct isp_match_data rk3399_isp_clk_data = {
> +	.clks = rk3399_isp_clks,
> +	.size = ARRAY_SIZE(rk3399_isp_clks),
> +};
> +
> +static const struct of_device_id rkisp1_plat_of_match[] = {
> +	{
> +		.compatible = "rockchip,rk3288-cif-isp",
> +		.data = &rk3288_isp_clk_data,
> +	}, {
> +		.compatible = "rockchip,rk3399-cif-isp",
> +		.data = &rk3399_isp_clk_data,
> +	},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, rkisp1_plat_of_match);
> +
> +static irqreturn_t rkisp1_irq_handler(int irq, void *ctx)
> +{
> +	struct device *dev = ctx;
> +	struct rkisp1_device *rkisp1_dev = dev_get_drvdata(dev);
> +	unsigned int mis_val;
> +
> +	mis_val = readl(rkisp1_dev->base_addr + CIF_ISP_MIS);
> +	if (mis_val)
> +		rkisp1_isp_isr(mis_val, rkisp1_dev);
> +
> +	mis_val = readl(rkisp1_dev->base_addr + CIF_MIPI_MIS);
> +	if (mis_val)
> +		rkisp1_mipi_isr(mis_val, rkisp1_dev);
> +
> +	mis_val = readl(rkisp1_dev->base_addr + CIF_MI_MIS);
> +	if (mis_val)
> +		rkisp1_mi_isr(mis_val, rkisp1_dev);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int rkisp1_plat_probe(struct platform_device *pdev)
> +{
> +	struct device_node *node = pdev->dev.of_node;
> +	const struct isp_match_data *clk_data;
> +	const struct of_device_id *match;
> +	struct device *dev = &pdev->dev;
> +	struct rkisp1_device *isp_dev;
> +	struct v4l2_device *v4l2_dev;
> +	unsigned int i;
> +	int ret, irq;
> +
> +	match = of_match_node(rkisp1_plat_of_match, node);
> +	isp_dev = devm_kzalloc(dev, sizeof(*isp_dev), GFP_KERNEL);
> +	if (!isp_dev)
> +		return -ENOMEM;
> +
> +	INIT_LIST_HEAD(&isp_dev->sensors);
> +
> +	dev_set_drvdata(dev, isp_dev);
> +	isp_dev->dev = dev;
> +
> +	isp_dev->base_addr = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(isp_dev->base_addr))
> +		return PTR_ERR(isp_dev->base_addr);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	ret = devm_request_irq(dev, irq, rkisp1_irq_handler, IRQF_SHARED,
> +			       dev_driver_string(dev), dev);
> +	if (ret < 0) {
> +		dev_err(dev, "request irq failed: %d\n", ret);
> +		return ret;
> +	}
> +
> +	isp_dev->irq = irq;
> +	clk_data = match->data;
> +
> +	for (i = 0; i < clk_data->size; i++)
> +		isp_dev->clks[i].id = clk_data->clks[i];
> +	ret = devm_clk_bulk_get(dev, clk_data->size, isp_dev->clks);
> +	if (ret)
> +		return ret;
> +	isp_dev->clk_size = clk_data->size;
> +
> +	atomic_set(&isp_dev->pipe.power_cnt, 0);
> +	atomic_set(&isp_dev->pipe.stream_cnt, 0);
> +	isp_dev->pipe.open = rkisp1_pipeline_open;
> +	isp_dev->pipe.close = rkisp1_pipeline_close;
> +	isp_dev->pipe.set_stream = rkisp1_pipeline_set_stream;
> +
> +	rkisp1_stream_init(isp_dev, RKISP1_STREAM_SP);
> +	rkisp1_stream_init(isp_dev, RKISP1_STREAM_MP);
> +
> +	strscpy(isp_dev->media_dev.model, "rkisp1",
> +		sizeof(isp_dev->media_dev.model));
> +	isp_dev->media_dev.dev = &pdev->dev;
> +	strscpy(isp_dev->media_dev.bus_info,
> +		"platform: " DRIVER_NAME, sizeof(isp_dev->media_dev.bus_info));
> +	media_device_init(&isp_dev->media_dev);
> +
> +	v4l2_dev = &isp_dev->v4l2_dev;
> +	v4l2_dev->mdev = &isp_dev->media_dev;
> +	strscpy(v4l2_dev->name, "rkisp1", sizeof(v4l2_dev->name));
> +	v4l2_ctrl_handler_init(&isp_dev->ctrl_handler, 5);
> +	v4l2_dev->ctrl_handler = &isp_dev->ctrl_handler;
> +
> +	ret = v4l2_device_register(isp_dev->dev, &isp_dev->v4l2_dev);
> +	if (ret < 0)

Once you've initialised the control handler, you'll need to free it in case
of an error. I.e. add one more label for that purpose near the end.

> +		return ret;
> +
> +	ret = media_device_register(&isp_dev->media_dev);
> +	if (ret < 0) {
> +		v4l2_err(v4l2_dev, "Failed to register media device: %d\n",
> +			 ret);
> +		goto err_unreg_v4l2_dev;
> +	}
> +
> +	/* create & register platefom subdev (from of_node) */
> +	ret = rkisp1_register_platform_subdevs(isp_dev);
> +	if (ret < 0)
> +		goto err_unreg_media_dev;
> +
> +	pm_runtime_enable(&pdev->dev);
> +
> +	return 0;
> +
> +err_unreg_media_dev:
> +	media_device_unregister(&isp_dev->media_dev);
> +err_unreg_v4l2_dev:
> +	v4l2_device_unregister(&isp_dev->v4l2_dev);
> +	return ret;
> +}
> +
> +static int rkisp1_plat_remove(struct platform_device *pdev)
> +{
> +	struct rkisp1_device *isp_dev = platform_get_drvdata(pdev);
> +
> +	pm_runtime_disable(&pdev->dev);
> +	media_device_unregister(&isp_dev->media_dev);
> +	v4l2_async_notifier_unregister(&isp_dev->notifier);
> +	v4l2_async_notifier_cleanup(&isp_dev->notifier);
> +	v4l2_device_unregister(&isp_dev->v4l2_dev);
> +	rkisp1_unregister_params_vdev(&isp_dev->params_vdev);
> +	rkisp1_unregister_stats_vdev(&isp_dev->stats_vdev);
> +	rkisp1_unregister_stream_vdevs(isp_dev);
> +	rkisp1_unregister_isp_subdev(isp_dev);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
> +{
> +	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> +
> +	clk_bulk_disable_unprepare(isp_dev->clk_size, isp_dev->clks);
> +	return pinctrl_pm_select_sleep_state(dev);
> +}
> +
> +static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
> +{
> +	struct rkisp1_device *isp_dev = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = pinctrl_pm_select_default_state(dev);
> +	if (ret < 0)
> +		return ret;
> +	ret = clk_bulk_prepare_enable(isp_dev->clk_size, isp_dev->clks);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops rkisp1_plat_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
> +				pm_runtime_force_resume)
> +	SET_RUNTIME_PM_OPS(rkisp1_runtime_suspend, rkisp1_runtime_resume, NULL)
> +};
> +
> +static struct platform_driver rkisp1_plat_drv = {
> +	.driver = {
> +		.name = DRIVER_NAME,
> +		.of_match_table = of_match_ptr(rkisp1_plat_of_match),
> +		.pm = &rkisp1_plat_pm_ops,
> +	},
> +	.probe = rkisp1_plat_probe,
> +	.remove = rkisp1_plat_remove,
> +};
> +
> +module_platform_driver(rkisp1_plat_drv);
> +MODULE_AUTHOR("Rockchip Camera/ISP team");
> +MODULE_DESCRIPTION("Rockchip ISP1 platform driver");
> +MODULE_LICENSE("Dual BSD/GPL");

BSD or MIT?

> diff --git a/drivers/media/platform/rockchip/isp1/dev.h b/drivers/media/platform/rockchip/isp1/dev.h
> new file mode 100644
> index 000000000000..f7cbee316523
> --- /dev/null
> +++ b/drivers/media/platform/rockchip/isp1/dev.h
> @@ -0,0 +1,97 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/*
> + * Rockchip isp1 driver
> + *
> + * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
> + */
> +
> +#ifndef _RKISP1_DEV_H
> +#define _RKISP1_DEV_H
> +
> +#include <linux/clk.h>
> +
> +#include "capture.h"
> +#include "rkisp1.h"
> +#include "isp_params.h"
> +#include "isp_stats.h"
> +
> +#define DRIVER_NAME "rkisp1"
> +#define ISP_VDEV_NAME DRIVER_NAME  "_ispdev"
> +#define SP_VDEV_NAME DRIVER_NAME   "_selfpath"
> +#define MP_VDEV_NAME DRIVER_NAME   "_mainpath"
> +#define DMA_VDEV_NAME DRIVER_NAME  "_dmapath"
> +
> +#define GRP_ID_SENSOR			BIT(0)
> +#define GRP_ID_MIPIPHY			BIT(1)
> +#define GRP_ID_ISP			BIT(2)
> +#define GRP_ID_ISP_MP			BIT(3)
> +#define GRP_ID_ISP_SP			BIT(4)
> +
> +#define RKISP1_MAX_BUS_CLK	8
> +#define RKISP1_MAX_SENSOR	2
> +#define RKISP1_MAX_PIPELINE	4
> +
> +/*
> + * struct rkisp1_pipeline - An ISP hardware pipeline
> + *
> + * Capture device call other devices via pipeline
> + *
> + * @num_subdevs: number of linked subdevs
> + * @power_cnt: pipeline power count
> + * @stream_cnt: stream power count
> + */
> +struct rkisp1_pipeline {
> +	struct media_pipeline pipe;
> +	int num_subdevs;
> +	atomic_t power_cnt;
> +	atomic_t stream_cnt;
> +	struct v4l2_subdev *subdevs[RKISP1_MAX_PIPELINE];
> +	int (*open)(struct rkisp1_pipeline *p,
> +		    struct media_entity *me, bool prepare);
> +	int (*close)(struct rkisp1_pipeline *p);
> +	int (*set_stream)(struct rkisp1_pipeline *p, bool on);
> +};
> +
> +/*
> + * struct rkisp1_sensor - Sensor information
> + * @mbus: media bus configuration
> + */
> +struct rkisp1_sensor {
> +	struct v4l2_subdev *sd;
> +	struct v4l2_mbus_config mbus;
> +	unsigned int lanes;
> +	struct phy *dphy;
> +	struct list_head list;
> +};

You seem to also have struct sensor_async_subdev that appears to contain
similar information. Would it be possible to unify the two?

This would appear to allow you getting rid of functions such as
sd_to_sensor, for instance.

> +
> +/*
> + * struct rkisp1_device - ISP platform device
> + * @base_addr: base register address
> + * @active_sensor: sensor in-use, set when streaming on
> + * @isp_sdev: ISP sub-device
> + * @rkisp1_stream: capture video device
> + * @stats_vdev: ISP statistics output device
> + * @params_vdev: ISP input parameters device
> + */
> +struct rkisp1_device {
> +	void __iomem *base_addr;
> +	int irq;
> +	struct device *dev;
> +	unsigned int clk_size;
> +	struct clk_bulk_data clks[RKISP1_MAX_BUS_CLK];
> +	struct v4l2_device v4l2_dev;
> +	struct v4l2_ctrl_handler ctrl_handler;
> +	struct media_device media_dev;
> +	struct v4l2_async_notifier notifier;
> +	struct v4l2_subdev *subdevs[RKISP1_SD_MAX];
> +	struct rkisp1_sensor *active_sensor;
> +	struct list_head sensors;
> +	struct rkisp1_isp_subdev isp_sdev;
> +	struct rkisp1_stream stream[RKISP1_MAX_STREAM];
> +	struct rkisp1_isp_stats_vdev stats_vdev;
> +	struct rkisp1_isp_params_vdev params_vdev;
> +	struct rkisp1_pipeline pipe;
> +	struct vb2_alloc_ctx *alloc_ctx;
> +};
> +
> +#endif

-- 
Regards,

Sakari Ailus
sakari.ailus@linux.intel.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 1/9] KVM: arm64: Document PV-time interface
From: Steven Price @ 2019-08-07 15:26 UTC (permalink / raw)
  To: Christophe de Dinechin
  Cc: KVM list, linux-doc, Marc Zyngier, open list, Russell King,
	Catalin Marinas, Paolo Bonzini, Will Deacon, kvmarm,
	linux-arm-kernel
In-Reply-To: <9F77FA64-C71B-4025-A58D-3AC07E6688DE@dinechin.org>

On 07/08/2019 15:28, Christophe de Dinechin wrote:
> 
> 
>> On 7 Aug 2019, at 15:21, Steven Price <steven.price@arm.com
>> <mailto:steven.price@arm.com>> wrote:
>>
>> On 05/08/2019 17:40, Christophe de Dinechin wrote:
>>>
>>> Steven Price writes:
>>>
>>>> Introduce a paravirtualization interface for KVM/arm64 based on the
>>>> "Arm Paravirtualized Time for Arm-Base Systems" specification DEN 0057A.
>>>>
>>>> This only adds the details about "Stolen Time" as the details of "Live
>>>> Physical Time" have not been fully agreed.
>>>>
>>> [...]
>>>
>>>> +
>>>> +Stolen Time
>>>> +-----------
>>>> +
>>>> +The structure pointed to by the PV_TIME_ST hypercall is as follows:
>>>> +
>>>> +  Field       | Byte Length | Byte Offset | Description
>>>> +  ----------- | ----------- | ----------- | --------------------------
>>>> +  Revision    |      4      |      0      | Must be 0 for version 0.1
>>>> +  Attributes  |      4      |      4      | Must be 0
>>>> +  Stolen time |      8      |      8      | Stolen time in unsigned
>>>> +              |             |             | nanoseconds indicating how
>>>> +              |             |             | much time this VCPU thread
>>>> +              |             |             | was involuntarily not
>>>> +              |             |             | running on a physical CPU.
>>>
>>> I know very little about the topic, but I don't understand how the spec
>>> as proposed allows an accurate reading of the relation between physical
>>> time and stolen time simultaneously. In other words, could you draw
>>> Figure 1 of the spec from within the guest? Or is it a non-objective?
>>
>> Figure 1 is mostly attempting to explain Live Physical Time (LPT), which
>> is not part of this patch series. But it does touch on stolen time by
>> the difference between "live physical time" and "virtual time".
>>
>> I'm not sure what you mean by "from within the guest". From the
>> perspective of the guest the parts of the diagram where the guest isn't
>> running don't exist (therefore there are discontinuities in the
>> "physical time" and "live physical time" lines).
> 
> I meant: If I run code within the guest that attempts to draw Figure 1,
> race conditions may cause the diagram actually drawn by your guest
> program to look completely wrong on occasions.
> 
>> This patch series doesn't attempt to provide the guest with a view of
>> "physical time" (or LPT) - but it might be able to observe that by
>> consulting something external (e.g. an NTP server, or an emulated RTC
>> which reports wall-clock time).
> 
> … with what appear to be like a built-in race condition, as you correctly
> identified. I was wondering if the built-in race condition was deliberate
> and/or necessary, or if it was irrelevant for the planned uses of the value.
> 
>> What it does provide is a mechanism for obtaining the difference (as
>> reported by the host) between "live physical time" and "virtual time" -
>> this is reported in nanoseconds in the above structure.
>>
>>> For example, if you read the stolen time before you read CNTVCT_EL0,
>>> isn't it possible for a lengthy event like a migration to occur between
>>> the two reads, causing the stolen time to be obsolete and off by seconds?
>>
>> "Lengthy events" like migration are represented by the "paused" state in
>> the diagram - i.e. it's the difference between "physical time" and "live
>> physical time". So stolen time doesn't attempt to represent that.
>>
>> And yes, there is a race between reading CNTVCT_EL0 and reading stolen
>> time - but in practice this doesn't really matter. The usual pseudo-code
>> way of using stolen time is:
> 
> I’m assuming this is the guest scheduler you are talking about,

yes

> and I’m assuming virtualization can preempt that code anywhere.
> Maybe that’s where I’m wrong?

You are correct, the guest can be preempted at any point.

> 
> For the sake of the argument, assume there is a 1s pause.
> Not completely unreasonable in a migration scenario.

As I mentioned before, events like migration are not represented by
stolen time. They would be represented by CNTVCT_EL0 appearing to pause
during the migration (so showing a difference between "physical time"
and "live physical time"). The stolen time value would not be incremented.

>>  * scheduler captures stolen time from structure and CNTVCT_EL0:
>>      before_timer = CNTVCT_EL0
> 
> [insert optional 1s pause here, case A]
> 
>>      before_stolen = stolen
>>  * schedule in process
>>  * process is pre-empted (or blocked in some way)
>>  * scheduler captures stolen time from structure and CNTVCT_EL0:
>>      after_timer = CNTVCT_EL0
> 
> [insert optional 1s pause here, case B]
> 
>>      after_stolen = stolen
>>      time = to_nsecs(after_timer - before_timer) -
>>             (after_stolen - before_stolen)
> 
> In case A, time is too big by one second. In case B, it is too small,
> to the point where your code might need to be ready for
> “time” unexpectedly showing up as negative.

So a 1 second pause is unlikely for stolen time - this means that the
VCPU was ready to run, but the host didn't run it for some reason. But
in theory you are correct this could happen. The core code deals with it
like this (update_rq_clock_task):
> 	if (static_key_false((&paravirt_steal_rq_enabled))) {
> 		steal = paravirt_steal_clock(cpu_of(rq));
> 		steal -= rq->prev_steal_time_rq;
> 
> 		if (unlikely(steal > delta))
> 			steal = delta;
> 
> 		rq->prev_steal_time_rq += steal;
> 		delta -= steal;
> 	}

So if (steal > delta) then steal is capped to delta, preventing the
final delta from going negative.

>>
>> The scheduler can then charge the process for "time" nanoseconds of
>> time. This ensures that a process isn't unfairly penalised if the host
>> doesn't schedule the VCPU while it is supposed to be running.
>>
>> The race is very small in comparison to the time the process is running,
>> and in the worst case just means the process is charged slightly more
>> (or less) than it should be.
> 
> At this point, what I don’t understand is why the race would be
> “very small” or why you would only be charged “slightly” more or less?

The window between measuring the time using CNTVCT_EL0 and getting the
stolen time from the hypervisor is pretty short. The amount of time that
is (normally) stolen in one go is also small. So the race is unlikely
and the error when it occurs is (usually) small.

Long events (such as migration or pausing the guest) are not considered
"stolen time" and should be reflected to the guest in other ways.

>> I guess if you're really worried about it, you could do a dance like:
>>
>> do {
>> before = stolen
>> timer = CNTVCT_EL0
>> after = stolen
>> } while (before != after);
> 
> That will work as long as nothing in that loop requires something
> that would cause `stolen` to jump. If there is such a guarantee,
> then that’s even efficient, because in most cases the loop
> would only run once, at the cost of one extra read and one test.

Note that other architectures don't have such loops, so arm64 is just
following the lead of existing architecture.

>> But I don't see the need to have such an accurate view of elapsed time
>> that the VCPU was scheduled. And of course at the moment (without this
>> series) the guest has no idea about time stolen by the host.
> 
> I’m certainly not arguing that exposing stolen time is a bad idea,
> I’m only wondering if the proposed solution is racy, and if so, if
> it is intentional.
> 
> If it’s indeed racy, the problem could be mitigated in a number of
> ways
> 
> a) document your loop or something similar as being the recommended
> way to avoid the race, and then ensure that the loop actually
> will always work as intended. The upside is that it’s just a change in
> some comments or documentation.
> 
> b) having a single interface that exposes multiple times. For example,
> you could have a copy of CNTVCT_EL0 written alongside stolen time,
> and then the scheduler could use that copy for its decision.

That would still be racy - the structure can be updated at any time (as
the host could interrupt the VCPU at any time), so you would still be
left with the problem of reading both atomically - which would mean
going back to the loop. This is the approach that LPT takes and is
documented in the spec.

Also I can't see why you would want to know the CNTVCT_EL0 value at the
point the stolen time was updated, it's much more useful to know the
current CNTVCT_EL0 value.

Ultimately reading the stolen time is always going to be slightly racy
because you are including some of the scheduler's time in the
calculation of how much time the process was running for. The pauses you
describe above are instances where time has been stolen from the
scheduler, but that time is being accounted for/against a user space
process. While the algorithm could be changed so that it's always a
positive for the user space process I'm not sure that's a benefit (it's
probably better that statistically it can go either way).

Steve


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [Sound-open-firmware] [PATCH v2 3/5] ASoC: SOF: Add DT DSP device support
From: Pierre-Louis Bossart @ 2019-08-07 15:22 UTC (permalink / raw)
  To: Daniel Baluta
  Cc: Mark Rutland, Aisheng Dong, Peng Fan, Fabio Estevam, Anson Huang,
	Devicetree List, Daniel Baluta, S.j. Wang, Marco Felsch,
	Linux Kernel Mailing List, Paul Olaru, Rob Herring, dl-linux-imx,
	Pengutronix Kernel Team, Leonard Crestez, Shawn Guo,
	linux-arm-kernel, sound-open-firmware
In-Reply-To: <CAEnQRZDctjdzQ2RjJXhQh+s=d0y_j3Taa51hDaR4bqJ62C=7iQ@mail.gmail.com>


>>>> +static int sof_dt_probe(struct platform_device *pdev)
>>>> +{
>>>> +     struct device *dev = &pdev->dev;
>>>> +     const struct sof_dev_desc *desc;
>>>> +     /*TODO: create a generic snd_soc_xxx_mach */
>>>> +     struct snd_soc_acpi_mach *mach;
>>>
>>> I wonder if you really need to use the same structures. For Intel we get
>>> absolutely zero info from the firmware so rely on an ACPI codec ID as a
>>> key to find information on which firmware and topology to use, and which
>>> machine driver to load. You could have all this information in a DT blob?
>>
>> Yes. I see your point. I will still need to make a generic structure for
>> snd_soc_acpi_mach so that everyone can use sof_nocodec_setup function.
>>
>> Maybe something like this:
>>
>> struct snd_soc_mach {
>>    union {
>>    struct snd_soc_acpi_mach acpi_mach;
>>    struct snd_soc_of_mach of_mach;
>>    }
>> };
>>
>> and then change the prototype of sof_nocodec_setup.
> 
> Hi Pierre,
> 
> I fixed all the comments except the one above. Replacing snd_soc_acpi_mach
> with a generic snd_soc_mach is not trivial task.
> 
> I wonder if it is acceptable to get the initial patches as they are
> now and later switch to
> generic ACPI/OF abstraction.
> 
> Asking this because for the moment on the i.MX side I have only
> implemented no codec
> version and we don't probe any of the machine drivers we have.
> 
> So, there is this only one member of snd_soc_acpi_mach that imx
> version is making use of:
> 
>    mach->drv_name = "sof-nocodec";
> 
> That's all.
> 
> I think the change as it is now is very clean and non-intrusive. Later
> we will get options to
> read firmware name and stuff from DT.
> 
> Anyhow, I don't think we can get rid of snd_dev_desc structure on
> i.MX. This will be used
> to store the information read from DT:
> 
> static struct sof_dev_desc sof_of_imx8qxp_desc = {
> »       .default_fw_path = "imx/sof",
> »       .default_tplg_path = "imx/sof-tplg",
> »       .nocodec_fw_filename = "sof-imx8.ri",
> »       .nocodec_tplg_filename = "sof-imx8-nocodec.tplg",
> »       .ops = &sof_imx8_ops,
> };
> 
> For the moment we will only use the default values.

Yes, that's fine for now. If you don't have a real machine driver then 
there's nothing urgent to change.

Is the new version on GitHub?

Thanks
-Pierre

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH] arm64: dts: rockchip: add rk3328 VPU node
From: Jonas Karlman @ 2019-08-07 15:20 UTC (permalink / raw)
  To: Heiko Stuebner
  Cc: devicetree@vger.kernel.org, Jonas Karlman, Arnaud Pouliquen,
	linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org,
	Rob Herring, linux-arm-kernel@lists.infradead.org

This patch add a VPU device node for rk3328.

Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
---
 arch/arm64/boot/dts/rockchip/rk3328.dtsi | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index e9fefd8a7e02..4a175fff2861 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -278,6 +278,7 @@
 			};
 			pd_vpu@RK3328_PD_VPU {
 				reg = <RK3328_PD_VPU>;
+				clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
 			};
 		};
 
@@ -596,6 +597,17 @@
 		status = "disabled";
 	};
 
+	vpu: video-codec@ff350000 {
+		compatible = "rockchip,rk3328-vpu";
+		reg = <0x0 0xff350000 0x0 0x800>;
+		interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vdpu";
+		clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+		clock-names = "aclk", "hclk";
+		iommus = <&vpu_mmu>;
+		power-domains = <&power RK3328_PD_VPU>;
+	};
+
 	vpu_mmu: iommu@ff350800 {
 		compatible = "rockchip,iommu";
 		reg = <0x0 0xff350800 0x0 0x40>;
@@ -604,7 +616,7 @@
 		clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
 		clock-names = "aclk", "iface";
 		#iommu-cells = <0>;
-		status = "disabled";
+		power-domains = <&power RK3328_PD_VPU>;
 	};
 
 	rkvdec_mmu: iommu@ff360480 {
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* RE: [PATCH] firmware: arm_scmi: Use {get,put}_unaligned_le32 accessors
From: David Laight @ 2019-08-07 15:18 UTC (permalink / raw)
  To: 'Sudeep Holla', linux-arm-kernel@lists.infradead.org
  Cc: linux-kernel@vger.kernel.org, Philipp Zabel
In-Reply-To: <20190807130038.26878-1-sudeep.holla@arm.com>

From: Sudeep Holla
> Sent: 07 August 2019 14:01
> 
> Instead of type-casting the {tx,rx}.buf all over the place while
> accessing them to read/write __le32 from/to the firmware, let's use
> the nice existing {get,put}_unaligned_le32 accessors to hide all the
> type cast ugliness.

Why the 'unaligned' accessors?

> -	*(__le32 *)t->tx.buf = cpu_to_le32(id);
> +	put_unaligned_le32(id, t->tx.buf);

These will be expensive if the cpu doesn't support them.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [RFCv3 2/3] interconnect: Add imx core driver
From: Georgi Djakov @ 2019-08-07 15:16 UTC (permalink / raw)
  To: Leonard Crestez, Rob Herring, Artur Świgoń,
	Alexandre Bailon, Viresh Kumar
  Cc: Mark Rutland, Dong Aisheng, Jacky Bai, Saravana Kannan,
	Anson Huang, Stephen Boyd, Michael Turquette, linux-pm,
	Krzysztof Kozlowski, Chanwoo Choi, Kyungmin Park, MyungJoo Ham,
	linux-imx, kernel, Fabio Estevam, Shawn Guo, devicetree,
	linux-arm-kernel
In-Reply-To: <2b8905754d9a3fa6f4dc7b73b45649c85aa3e80a.1565088423.git.leonard.crestez@nxp.com>

Hi Leonard,

On 8/6/19 13:55, Leonard Crestez wrote:
> This adds support for i.MX SoC family to interconnect framework.
> 
> Platform drivers can describe their interconnect graph and
> several adjustment knobs where an icc node bandwith converted to a

s/bandwith/bandwidth/

> clk_min_rate request.
> 
> All adjustable nodes are assumed to be independent.
> 
> Based on an earlier work by Alexandre Bailon but greatly reduced to drop
> "platform opp" support.
> 
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> Signed-off-by: Alexandre Bailon <abailon@baylibre.com>

Your Signed-off-by should be below Alexandre's.

> ---
>  drivers/interconnect/Kconfig      |   1 +
>  drivers/interconnect/Makefile     |   1 +
>  drivers/interconnect/imx/Kconfig  |   5 +
>  drivers/interconnect/imx/Makefile |   1 +
>  drivers/interconnect/imx/imx.c    | 258 ++++++++++++++++++++++++++++++
>  drivers/interconnect/imx/imx.h    |  62 +++++++
>  6 files changed, 328 insertions(+)
>  create mode 100644 drivers/interconnect/imx/Kconfig
>  create mode 100644 drivers/interconnect/imx/Makefile
>  create mode 100644 drivers/interconnect/imx/imx.c
>  create mode 100644 drivers/interconnect/imx/imx.h
> 
> diff --git a/drivers/interconnect/Kconfig b/drivers/interconnect/Kconfig
> index bfa4ca3ab7a9..e61802230f90 100644
> --- a/drivers/interconnect/Kconfig
> +++ b/drivers/interconnect/Kconfig
> @@ -10,7 +10,8 @@ menuconfig INTERCONNECT
>  	  If unsure, say no.
>  
>  if INTERCONNECT
>  
>  source "drivers/interconnect/qcom/Kconfig"
> +source "drivers/interconnect/imx/Kconfig"
>  
>  endif
> diff --git a/drivers/interconnect/Makefile b/drivers/interconnect/Makefile
> index 28f2ab0824d5..20a13b7eb37f 100644
> --- a/drivers/interconnect/Makefile
> +++ b/drivers/interconnect/Makefile
> @@ -2,5 +2,6 @@
>  
>  icc-core-objs				:= core.o
>  
>  obj-$(CONFIG_INTERCONNECT)		+= icc-core.o
>  obj-$(CONFIG_INTERCONNECT_QCOM)		+= qcom/
> +obj-$(CONFIG_INTERCONNECT_IMX)		+= imx/
> diff --git a/drivers/interconnect/imx/Kconfig b/drivers/interconnect/imx/Kconfig
> new file mode 100644
> index 000000000000..45fbae7007af
> --- /dev/null
> +++ b/drivers/interconnect/imx/Kconfig
> @@ -0,0 +1,5 @@
> +config INTERCONNECT_IMX
> +	bool "i.MX interconnect drivers"
> +	depends on ARCH_MXC || ARCH_MXC_ARM64 || COMPILE_TEST
> +	help
> +	  Generic interconnect driver for i.MX SOCs
> diff --git a/drivers/interconnect/imx/Makefile b/drivers/interconnect/imx/Makefile
> new file mode 100644
> index 000000000000..bb92fd9fe4a5
> --- /dev/null
> +++ b/drivers/interconnect/imx/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_INTERCONNECT_IMX) += imx.o
> diff --git a/drivers/interconnect/imx/imx.c b/drivers/interconnect/imx/imx.c
> new file mode 100644
> index 000000000000..cc838e40419e
> --- /dev/null
> +++ b/drivers/interconnect/imx/imx.c
> @@ -0,0 +1,258 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Interconnect framework driver for i.MX SoC
> + *
> + * Copyright (c) 2019, BayLibre
> + * Copyright (c) 2019, NXP
> + * Author: Alexandre Bailon <abailon@baylibre.com>
> + * Author: Leonard Crestez <leonard.crestez@nxp.com>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/interconnect-provider.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_qos.h>
> +#include <linux/devfreq.h>

Please sort alphabetically.

> +#include <linux/of.h>
> +
> +#include "imx.h"
> +
> +/* private icc_provider data */
> +struct imx_icc_provider {
> +	struct device *dev;
> +};
> +
> +/* private icc_node data */
> +struct imx_icc_node {
> +	const struct imx_icc_node_desc *desc;
> +	struct devfreq *devfreq;
> +	struct dev_pm_qos_request qos_req;
> +};
> +
> +static int imx_icc_aggregate(struct icc_node *node, u32 avg_bw,
> +				  u32 peak_bw, u32 *agg_avg, u32 *agg_peak)
> +{
> +	*agg_avg += avg_bw;
> +	*agg_peak = max(*agg_peak, peak_bw);
> +
> +	return 0;
> +}
> +
> +static struct icc_node* imx_icc_xlate(struct of_phandle_args *spec, void *data)
> +{
> +	struct imx_icc_provider *desc = data;
> +	struct icc_provider *provider = dev_get_drvdata(desc->dev);
> +	unsigned int id = spec->args[0];
> +	struct icc_node *node;
> +
> +	list_for_each_entry (node, &provider->nodes, node_list)
> +		if (node->id == id)
> +			return node;
> +
> +	return ERR_PTR(-EINVAL);
> +}
> +
> +static int imx_icc_node_set(struct icc_node *node)
> +{
> +	struct device *dev = node->provider->dev;
> +	struct imx_icc_node *node_data = node->data;
> +	unsigned long freq;
> +
> +	if (!node_data->devfreq)
> +		return 0;
> +
> +	freq = (node->avg_bw + node->peak_bw) * node_data->desc->adj->bw_mul;
> +	do_div(freq, node_data->desc->adj->bw_div);
> +	if (freq > INT_MAX) {
> +		dev_err(dev, "%s can't request more INT_MAX freq\n",
> +				node->name);
> +		return -ERANGE;
> +	}
> +
> +	dev_dbg(dev, "%s avg_bw %u peak_bw %u min_freq %lu\n",
> +			node->name, node->avg_bw, node->peak_bw, freq);
> +
> +	dev_pm_qos_update_request(&node_data->qos_req, freq);
> +
> +	return 0;
> +}
> +
> +static int imx_icc_set(struct icc_node *src, struct icc_node *dst)
> +{
> +	return imx_icc_node_set(dst);
> +}
> +
> +static int imx_icc_node_init_devfreq(struct device *dev, 
> +				     struct icc_node *node)
> +{
> +	struct imx_icc_node *node_data = node->data;
> +	const struct imx_icc_node_desc *node_desc = node_data->desc;
> +	int index;
> +	int ret;
> +
> +	index = of_property_match_string(dev->of_node,
> +			"devfreq-names", node_desc->adj->devfreq_name);
> +	if (index < 0) {
> +		dev_err(dev, "failed to match devfreq-names %s: %d\n",
> +				node_desc->adj->devfreq_name, index);
> +		return index;
> +	}
> +
> +	node_data->devfreq = devfreq_get_devfreq_by_phandle(dev, index);
> +	if (IS_ERR(node_data->devfreq)) {
> +		ret = PTR_ERR(node_data->devfreq);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(dev, "failed to fetch devfreq %d %s: %d\n",
> +					index, node_desc->adj->devfreq_name, ret);
> +		return ret;
> +	}
> +
> +	return dev_pm_qos_add_request(node_data->devfreq->dev.parent,
> +			&node_data->qos_req,
> +			DEV_PM_QOS_MIN_FREQUENCY, 0);
> +}
> +
> +static struct icc_node *imx_icc_node_add(struct icc_provider *provider,
> +					 const struct imx_icc_node_desc *node_desc)
> +{
> +	struct imx_icc_provider *provider_data = provider->data;
> +	struct device *dev = provider_data->dev;
> +	struct imx_icc_node *node_data;
> +	struct icc_node *node;
> +	int ret;
> +
> +	node = icc_node_create(node_desc->id);
> +	if (IS_ERR(node)) {
> +		dev_err(dev, "failed to create node %d\n", node_desc->id);
> +		return node;
> +	}
> +
> +	if (node->data) {
> +		dev_err(dev, "already created node %s id=%d\n",
> +				node_desc->name, node_desc->id);
> +		return ERR_PTR(-EEXIST);
> +	}
> +
> +	node_data = devm_kzalloc(dev, sizeof(*node_data), GFP_KERNEL);
> +	if (!node_data) {
> +		icc_node_destroy(node->id);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	node->name = node_desc->name;
> +	node->data = node_data;
> +	node_data->desc = node_desc;
> +	if (node_desc->adj) {
> +		ret = imx_icc_node_init_devfreq(dev, node);
> +		if (ret < 0) {
> +			icc_node_destroy(node->id);
> +			return ERR_PTR(ret);
> +		}
> +	}
> +
> +	icc_node_add(node, provider);
> +
> +	return node;
> +}
> +
> +static void imx_icc_unregister_nodes(struct icc_provider *provider)
> +{
> +	struct icc_node *node, *tmp;
> +
> +	list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
> +		struct imx_icc_node *node_data = node->data;
> +
> +		icc_node_del(node);
> +		icc_node_destroy(node->id);
> +		if (dev_pm_qos_request_active(&node_data->qos_req))
> +			dev_pm_qos_remove_request(&node_data->qos_req);
> +	}
> +}
> +
> +static int imx_icc_register_nodes(struct icc_provider *provider,
> +				  const struct imx_icc_node_desc *descs,
> +				  int count)
> +{
> +	int ret;
> +	int i;
> +
> +	for (i = 0; i < count; i++) {
> +		struct icc_node *node;
> +		const struct imx_icc_node_desc *node_desc = &descs[i];
> +		size_t j;
> +
> +		node = imx_icc_node_add(provider, node_desc);
> +		if (IS_ERR(node)) {
> +			ret = PTR_ERR(node);
> +			if (ret != -EPROBE_DEFER)
> +				dev_err(provider->dev, "failed to add %s: %d\n",
> +						node_desc->name, ret);
> +			goto err;
> +		}
> +
> +		for (j = 0; j < node_desc->num_links; j++)
> +			icc_link_create(node, node_desc->links[j]);
> +	}
> +
> +	return 0;
> +
> +err:
> +	imx_icc_unregister_nodes(provider);
> +
> +	return ret;
> +}
> +
> +int imx_icc_register(struct platform_device *pdev,
> +		     struct imx_icc_node_desc *nodes, int nodes_count)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct imx_icc_provider *desc;
> +	struct icc_provider *provider;
> +	int ret;
> +
> +	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
> +	if (!desc)
> +		return -ENOMEM;
> +	desc->dev = dev;
> +
> +	provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
> +	if (!provider)
> +		return -ENOMEM;
> +	provider->set = imx_icc_set;
> +	provider->aggregate = imx_icc_aggregate;
> +	provider->xlate = imx_icc_xlate;
> +	provider->data = desc;
> +	provider->dev = dev;
> +	platform_set_drvdata(pdev, provider);
> +
> +	ret = icc_provider_add(provider);
> +	if (ret) {
> +		dev_err(dev, "error adding interconnect provider\n");
> +		return ret;
> +	}
> +
> +	ret = imx_icc_register_nodes(provider, nodes, nodes_count);
> +	if (ret) {
> +		dev_err(dev, "error adding interconnect nodes\n");
> +		goto provider_del;
> +	}
> +
> +	return 0;
> +
> +provider_del:
> +	icc_provider_del(provider);
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(imx_icc_register);
> +
> +int imx_icc_unregister(struct platform_device *pdev)
> +{
> +	struct icc_provider *provider = platform_get_drvdata(pdev);
> +
> +	icc_provider_del(provider);
> +	imx_icc_unregister_nodes(provider);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(imx_icc_unregister);
> diff --git a/drivers/interconnect/imx/imx.h b/drivers/interconnect/imx/imx.h
> new file mode 100644
> index 000000000000..ab191eb89616
> --- /dev/null
> +++ b/drivers/interconnect/imx/imx.h
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Interconnect framework driver for i.MX SoC
> + *
> + * Copyright (c) 2019, BayLibre
> + * Copyright (c) 2019, NXP
> + * Author: Alexandre Bailon <abailon@baylibre.com>
> + * Author: Leonard Crestez <leonard.crestez@nxp.com>
> + */
> +#ifndef __BUSFREQ_H
> +#define __BUSFREQ_H

Maybe __DRIVERS_INTERCONNECT_IMX_IMX_H to match with the path and filename.

> +
> +#include <linux/kernel.h>
> +
> +#define IMX_ICC_MAX_LINKS	32

2 seems enough?

> +#define IMX_ICC_UNDEFINED_BW	0xffffffff

Is this used?

> +
> +/*
> + * struct imx_icc_node_adj - Describe an dynamic adjustment knob

s/an/a/

> + */
> +struct imx_icc_node_adj_desc {
> +	const char *devfreq_name;
> +	unsigned int bw_mul, bw_div;
> +};
> +
> +/*
> + * struct imx_icc_node - Describe an interconnect node
> + * @name: name of the node
> + * @id: an unique id to identify the node
> + * @links: an array of slaves' node id
> + * @num_links: number of id defined in links
> + */
> +struct imx_icc_node_desc {
> +	const char *name;
> +	u16 id;
> +	u16 links[IMX_ICC_MAX_LINKS];
> +	u16 num_links;
> +
> +	const struct imx_icc_node_adj_desc *adj;
> +};
> +
> +#define DEFINE_BUS_INTERCONNECT(_name, _id, _adj, _numlinks, ...)	\

You can remove the _numlinks...

> +	{								\
> +		.id = _id,						\
> +		.name = _name,						\
> +		.adj = _adj,						\
> +		.num_links = _numlinks,					\

...and calculate the number of links automatically with:
		.num_links = ARRAY_SIZE(((int[]){ __VA_ARGS__ })),	\

> +		.links = { __VA_ARGS__ },				\
> +	}
> +
> +#define DEFINE_BUS_MASTER(_name, _id, _dest_id)				\
> +	DEFINE_BUS_INTERCONNECT(_name, _id, NULL, 1, _dest_id)
> +
> +#define DEFINE_BUS_SLAVE(_name, _id, _adj)				\
> +	DEFINE_BUS_INTERCONNECT(_name, _id, _adj, 0)
> +
> +int imx_icc_register(struct platform_device *pdev,
> +		     struct imx_icc_node_desc *nodes,
> +		     int nodes_count);
> +int imx_icc_unregister(struct platform_device *pdev);
> +
> +#endif /* __BUSFREQ_H */
Thanks,
Georgi



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [RFCv3 1/3] dt-bindings: interconnect: Add bindings for imx
From: Georgi Djakov @ 2019-08-07 15:16 UTC (permalink / raw)
  To: Leonard Crestez, Rob Herring, Artur Świgoń,
	Alexandre Bailon, Viresh Kumar
  Cc: Mark Rutland, Dong Aisheng, Jacky Bai, Saravana Kannan,
	Anson Huang, Stephen Boyd, Michael Turquette, linux-pm,
	Krzysztof Kozlowski, Chanwoo Choi, Kyungmin Park, MyungJoo Ham,
	linux-imx, kernel, Fabio Estevam, Shawn Guo, devicetree,
	linux-arm-kernel
In-Reply-To: <90561b14af66655ca859d387b3808a84641eea4e.1565088423.git.leonard.crestez@nxp.com>

Hi Leonard,

On 8/6/19 13:55, Leonard Crestez wrote:
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> ---

Please put some commit text.

>  .../devicetree/bindings/interconnect/imx.yaml | 38 +++++++++++++++++++
>  1 file changed, 38 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interconnect/imx.yaml
> 
> diff --git a/Documentation/devicetree/bindings/interconnect/imx.yaml b/Documentation/devicetree/bindings/interconnect/imx.yaml
> new file mode 100644
> index 000000000000..c6f173b38f4f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interconnect/imx.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/interconnect/imx.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Generic i.MX interconnect device
> +
> +maintainers:
> +  - Leonard Crestez <leonard.crestez@nxp.com>
> +
> +properties:
> +  compatible:
> +    contains:
> +      enum:
> +        - fsl,imx8mm-interconnect

Maybe fsl,imx8mm-busfreq? I thought it's called busfreq in downstream, but it's
up to you.

> +  "#interconnect-cells":
> +    const: 1
> +  devfreq-names:
> +    description: Names of devfreq instances for adjustable nodes
> +  devfreq:
> +    description: List of phandle pointing to devfreq instances
> +
> +required:
> +  - compatible
> +  - "#interconnect-cells"
> +  - "devfreq-names"
> +  - "devfreq"
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interconnect/imx8mm.h>
> +    icc: interconnect {
> +        compatible = "fsl,imx8mm-interconnect";
> +        #interconnect-cells = <1>;
> +        devfreq-names = "dram", "noc", "axi";
> +        devfreq = <&ddrc>, <&noc>, <&pl301_main>;
> +    };
> 

Thanks,
Georgi

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] arm64: KVM: hyp: debug-sr: Mark expected switch fall-throughs
From: Marc Zyngier @ 2019-08-07 15:11 UTC (permalink / raw)
  To: Gustavo A. R. Silva, James Morse, Julien Thierry,
	Suzuki K Poulose, Catalin Marinas, Will Deacon
  Cc: kvmarm, linux-arm-kernel, linux-kernel
In-Reply-To: <20190807141857.GA4198@embeddedor>

On 07/08/2019 15:18, Gustavo A. R. Silva wrote:
> Mark switch cases where we are expecting to fall through.
> 
> This patch fixes the following warnings (Building: allmodconfig arm64):
> 
> arch/arm64/kvm/hyp/debug-sr.c:20:19: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:21:19: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:22:19: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:23:19: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:24:19: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:25:19: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:26:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:27:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:28:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:29:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:30:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:31:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:32:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:33:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> arch/arm64/kvm/hyp/debug-sr.c:34:18: warning: this statement may fall through [-Wimplicit-fallthrough=]
> 
> Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>

Already fixed (together with all the other KVM/arm warnings/bugs), and
pull request sent to Paolo.

Thanks,

	M.
-- 
Jazz is not dead, it just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* RE: [PATCH v2 2/4] perf: Use CAP_SYS_ADMIN with perf_event_paranoid checks
From: Lubashev, Igor @ 2019-08-07 14:56 UTC (permalink / raw)
  To: Jiri Olsa, Alexey Budankov
  Cc: Mathieu Poirier, Suzuki K Poulose, Peter Zijlstra,
	linux-kernel@vger.kernel.org, Arnaldo Carvalho de Melo,
	James Morris, Alexander Shishkin, Ingo Molnar, Namhyung Kim,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190807114602.GB9605@krava>

On Wed, August 7 at 2019 7:46 AM Jiri Olsa wrote:
> On Tue, Aug 06, 2019 at 11:35:55PM -0400, Igor Lubashev wrote:
> > The kernel is using CAP_SYS_ADMIN instead of euid==0 to override
> > perf_event_paranoid check. Make perf do the same.
> >
> > Signed-off-by: Igor Lubashev <ilubashe@akamai.com>
> > ---
> >  tools/perf/arch/arm/util/cs-etm.c    | 3 ++-
> >  tools/perf/arch/arm64/util/arm-spe.c | 4 ++--
> > tools/perf/arch/x86/util/intel-bts.c | 3 ++-
> > tools/perf/arch/x86/util/intel-pt.c  | 2 +-
> >  tools/perf/util/evsel.c              | 2 +-
> >  5 files changed, 8 insertions(+), 6 deletions(-)
> >
SNIP
> > --- a/tools/perf/arch/arm64/util/arm-spe.c
> > +++ b/tools/perf/arch/arm64/util/arm-spe.c
> > @@ -12,6 +12,7 @@
> >  #include <time.h>
> >
> >  #include "../../util/cpumap.h"
> > +#include "../../util/event.h"
> >  #include "../../util/evsel.h"
> >  #include "../../util/evlist.h"
> >  #include "../../util/session.h"
> > @@ -65,8 +66,7 @@ static int arm_spe_recording_options(struct
> auxtrace_record *itr,
> >  	struct arm_spe_recording *sper =
> >  			container_of(itr, struct arm_spe_recording, itr);
> >  	struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
> > -	struct evsel *evsel, *arm_spe_evsel = NULL;
> 
> wouldn't this removal break the compilation on arm?
> 
> jirka
> 
> > -	bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
> > +	bool privileged = perf_event_paranoid_check(-1);
> >  	struct evsel *tracking_evsel;
> >  	int err;
> 
> SNIP

Mea culpa!  (An artifact of a bad rebase.)  Just learned to cross-compile.  Thanks, Alexey and Jirka!

The v3 with the fix has been posted (https://lkml.kernel.org/lkml/cover.1565188228.git.ilubashe@akamai.com).

- Igor

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH V4 11/11] docs: arm64: Add layout and 52-bit info to memory document
From: Will Deacon @ 2019-08-07 14:55 UTC (permalink / raw)
  To: Steve Capper
  Cc: crecklin@redhat.com, ard.biesheuvel@linaro.org, Catalin Marinas,
	bhsharma@redhat.com, maz@kernel.org, nd,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190807132935.GB17012@capper-ampere.manchester.arm.com>

On Wed, Aug 07, 2019 at 01:29:38PM +0000, Steve Capper wrote:
> Many thanks for going through this series Catalin. Would you like me to post
> a V5 of the series?

/me does best Catalin impression...

"Yes, please."

Uncanny, eh?

Will

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox