Re: [PATCH] irqchip/gic-v3: Fix IPRIORITYR can't perform byte operations in GIC-600

2021-03-30 Thread Lecopzer Chen
[...]
> > > > 
> > > > From the architecture spec:
> > > > 
> > > > 
> > > > 11.1.3 GIC memory-mapped register access
> > > > 
> > > > In any system, access to the following registers must be supported:
> > > > 
> > > > [...]
> > > > * Byte accesses to:
> > > > - GICD_IPRIORITYR.
> > > > - GICD_ITARGETSR.
> > > > - GICD_SPENDSGIR.
> > > > - GICD_CPENDSGIR.
> > > > - GICR_IPRIORITYR.
> > > > 
> > > > 
> > > > So if GIC600 doesn't follow this architectural requirement, this is a
> > > > HW erratum, and I want an actual description of the HW issue together
> > > > with an erratum number.
> > > > 
> > > > Lorenzo, can you please investigate on your side?
> > > 
> > > Sure - I will look into it and report back.
> > 
> > Checked - I don't think this patch is needed so it should be dropped and
> > a follow-up discussion can continue in the relevant/appropriate forum -
> > if there is anything left to discuss.
> 
> Thanks for having had a look. This really smells like an integration
> issue rather than an actual GIC bug.
> 
> Lecopzer, please check with your HW people and potentially ARM, as I
> think you are looking at the wrong problem.

Thanks a lot for the suggestion and checking,

I think I'll back to disscuss with ARM and our HW team to figure out
the previous answer from ARM Support in detail.

Thanks again!


Lecopzer


[PATCH] irqchip/gic-v3: Fix IPRIORITYR can't perform byte operations in GIC-600

2021-03-30 Thread Lecopzer Chen
When pseudo-NMI enabled, register_nmi() set priority of specific IRQ
by byte ops, and this doesn't work in GIC-600.

We have asked ARM Support [1]:
> Please refer to following description in
> "2.1.2 Distributor ACE-Lite slave interface" of GIC-600 TRM for
> the GIC600 ACE-lite slave interface supported sizes:
>   "The GIC-600 only accepts single beat accesses of the sizes for
>   each register that are shown in the Programmers model,
>   see Chapter 4 Programmer's model on page 4-102.
>   All other accesses are rejected and given either an
>   OKAY or SLVERR response that is based on the GICT_ERR0CTLR.UE bit.".

Thus the register needs to be written by double word operation and
the step will be: read 32bit, set byte and write it back.

[1] https://services.arm.com/support/s/case/5003t1L4Pba

Signed-off-by: Lecopzer Chen 
---
 drivers/irqchip/irq-gic-v3.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index eb0ee356a629..cfc5a6ad30dc 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -440,10 +440,21 @@ static void gic_irq_set_prio(struct irq_data *d, u8 prio)
 {
void __iomem *base = gic_dist_base(d);
u32 offset, index;
+   u32 val, prio_offset_mask, prio_offset_shift;
 
offset = convert_offset_index(d, GICD_IPRIORITYR, );
 
-   writeb_relaxed(prio, base + offset + index);
+   /*
+* GIC-600 memory mapping register doesn't support byte opteration,
+* thus read 32-bits from register, set bytes and wtire back to it.
+*/
+   prio_offset_shift = (index & 0x3) * 8;
+   prio_offset_mask = GENMASK(prio_offset_shift + 7, prio_offset_shift);
+   index &= ~0x3;
+   val = readl_relaxed(base + offset + index);
+   val &= ~prio_offset_mask;
+   val |= prio << prio_offset_shift;
+   writel_relaxed(val, base + offset + index);
 }
 
 static u32 gic_get_ppi_index(struct irq_data *d)
-- 
2.18.0



Re: [PATCH v5] arm64: Enable perf events based hard lockup detector

2021-03-30 Thread Lecopzer Chen
> > Hi Will, Mark,
> > 
> > On Fri, 15 Jan 2021 at 17:32, Sumit Garg  wrote:
> > >
> > > With the recent feature added to enable perf events to use pseudo NMIs
> > > as interrupts on platforms which support GICv3 or later, its now been
> > > possible to enable hard lockup detector (or NMI watchdog) on arm64
> > > platforms. So enable corresponding support.
> > >
> > > One thing to note here is that normally lockup detector is initialized
> > > just after the early initcalls but PMU on arm64 comes up much later as
> > > device_initcall(). So we need to re-initialize lockup detection once
> > > PMU has been initialized.
> > >
> > > Signed-off-by: Sumit Garg 
> > > ---
> > >
> > > Changes in v5:
> > > - Fix lockup_detector_init() invocation to be rather invoked from CPU
> > >   binded context as it makes heavy use of per-cpu variables and shouldn't
> > >   be invoked from preemptible context.
> > >
> > 
> > Do you have any further comments on this?
> > 
> > Lecopzer,
> > 
> > Does this feature work fine for you now?
> 
> This really fixes the warning, I have a real hardware for testing this now.
> but do we need to call lockup_detector_init() for each cpu?
> 
> In init/main.c, it's only called by cpu 0 for once.
 
Oh sorry, I just misread the code, please ignore previous mail.
 

BRs,
Lecopzer


Re: [PATCH v4 5/5] arm64: Kconfig: select KASAN_VMALLOC if KANSAN_GENERIC is enabled

2021-03-30 Thread Lecopzer Chen
> On Wed, Mar 24, 2021 at 12:05:22PM +0800, Lecopzer Chen wrote:
> > Before this patch, someone who wants to use VMAP_STACK when
> > KASAN_GENERIC enabled must explicitly select KASAN_VMALLOC.
> > 
> > From Will's suggestion [1]:
> >   > I would _really_ like to move to VMAP stack unconditionally, and
> >   > that would effectively force KASAN_VMALLOC to be set if KASAN is in use
> > 
> > Because VMAP_STACK now depends on either HW_TAGS or KASAN_VMALLOC if
> > KASAN enabled, in order to make VMAP_STACK selected unconditionally,
> > we bind KANSAN_GENERIC and KASAN_VMALLOC together.
> > 
> > Note that SW_TAGS supports neither VMAP_STACK nor KASAN_VMALLOC now,
> > so this is the first step to make VMAP_STACK selected unconditionally.
> 
> Do you know if anybody is working on this? It's really unfortunate that
> we can't move exclusively to VMAP_STACK just because of SW_TAGS KASAN.
> 
> That said, what is there to do? As things stand, won't kernel stack
> addresses end up using KASAN_TAG_KERNEL?


Hi Andrey,

Do you or any KASAN developers have already had any plan for this?



thanks,
Lecopzer


Re: [PATCH v5] arm64: Enable perf events based hard lockup detector

2021-03-30 Thread Lecopzer Chen
> Hi Will, Mark,
> 
> On Fri, 15 Jan 2021 at 17:32, Sumit Garg  wrote:
> >
> > With the recent feature added to enable perf events to use pseudo NMIs
> > as interrupts on platforms which support GICv3 or later, its now been
> > possible to enable hard lockup detector (or NMI watchdog) on arm64
> > platforms. So enable corresponding support.
> >
> > One thing to note here is that normally lockup detector is initialized
> > just after the early initcalls but PMU on arm64 comes up much later as
> > device_initcall(). So we need to re-initialize lockup detection once
> > PMU has been initialized.
> >
> > Signed-off-by: Sumit Garg 
> > ---
> >
> > Changes in v5:
> > - Fix lockup_detector_init() invocation to be rather invoked from CPU
> >   binded context as it makes heavy use of per-cpu variables and shouldn't
> >   be invoked from preemptible context.
> >
> 
> Do you have any further comments on this?
> 
> Lecopzer,
> 
> Does this feature work fine for you now?

This really fixes the warning, I have a real hardware for testing this now.
but do we need to call lockup_detector_init() for each cpu?

In init/main.c, it's only called by cpu 0 for once.


BRs,
Lecopzer


[PATCH v4 4/5] arm64: kaslr: support randomized module area with KASAN_VMALLOC

2021-03-23 Thread Lecopzer Chen
After KASAN_VMALLOC works in arm64, we can randomize module region
into vmalloc area now.

Test:
VMALLOC area ffc01000 fffdf000

before the patch:
module_alloc_base/end ffc008b8 ffc01000
after the patch:
module_alloc_base/end ffdcf4bed000 ffc01000

And the function that insmod some modules is fine.

Suggested-by: Ard Biesheuvel 
Signed-off-by: Lecopzer Chen 
---
 arch/arm64/kernel/kaslr.c  | 18 ++
 arch/arm64/kernel/module.c | 16 +---
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
index 27f8939deb1b..341342b207f6 100644
--- a/arch/arm64/kernel/kaslr.c
+++ b/arch/arm64/kernel/kaslr.c
@@ -128,15 +128,17 @@ u64 __init kaslr_early_init(void)
/* use the top 16 bits to randomize the linear region */
memstart_offset_seed = seed >> 48;
 
-   if (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
-   IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+   if (!IS_ENABLED(CONFIG_KASAN_VMALLOC) &&
+   (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
+IS_ENABLED(CONFIG_KASAN_SW_TAGS)))
/*
-* KASAN does not expect the module region to intersect the
-* vmalloc region, since shadow memory is allocated for each
-* module at load time, whereas the vmalloc region is shadowed
-* by KASAN zero pages. So keep modules out of the vmalloc
-* region if KASAN is enabled, and put the kernel well within
-* 4 GB of the module region.
+* KASAN without KASAN_VMALLOC does not expect the module region
+* to intersect the vmalloc region, since shadow memory is
+* allocated for each module at load time, whereas the vmalloc
+* region is shadowed by KASAN zero pages. So keep modules
+* out of the vmalloc region if KASAN is enabled without
+* KASAN_VMALLOC, and put the kernel well within 4 GB of the
+* module region.
 */
return offset % SZ_2G;
 
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index fe21e0f06492..b5ec010c481f 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -40,14 +40,16 @@ void *module_alloc(unsigned long size)
NUMA_NO_NODE, __builtin_return_address(0));
 
if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
-   !IS_ENABLED(CONFIG_KASAN_GENERIC) &&
-   !IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+   (IS_ENABLED(CONFIG_KASAN_VMALLOC) ||
+(!IS_ENABLED(CONFIG_KASAN_GENERIC) &&
+ !IS_ENABLED(CONFIG_KASAN_SW_TAGS
/*
-* KASAN can only deal with module allocations being served
-* from the reserved module region, since the remainder of
-* the vmalloc region is already backed by zero shadow pages,
-* and punching holes into it is non-trivial. Since the module
-* region is not randomized when KASAN is enabled, it is even
+* KASAN without KASAN_VMALLOC can only deal with module
+* allocations being served from the reserved module region,
+* since the remainder of the vmalloc region is already
+* backed by zero shadow pages, and punching holes into it
+* is non-trivial. Since the module region is not randomized
+* when KASAN is enabled without KASAN_VMALLOC, it is even
 * less likely that the module region gets exhausted, so we
 * can simply omit this fallback in that case.
 */
-- 
2.25.1



[PATCH v4 1/5] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-03-23 Thread Lecopzer Chen
Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Like how the MODULES_VADDR does now, just not to early populate
the VMALLOC_START between VMALLOC_END.

Before:

MODULE_VADDR: no mapping, no zero shadow at init
VMALLOC_VADDR: backed with zero shadow at init

After:

MODULE_VADDR: no mapping, no zero shadow at init
VMALLOC_VADDR: no mapping, no zero shadow at init

Thus the mapping will get allocated on demand by the core function
of KASAN_VMALLOC.

  ---  vmalloc_shadow_start
 |   |
 |   |
 |   | <= non-mapping
 |   |
 |   |
 |---|
 |///|<- kimage shadow with page table mapping.
 |---|
 |   |
 |   | <= non-mapping
 |   |
 - vmalloc_shadow_end
 |000|
 |000| <= Zero shadow
 |000|
 - KASAN_SHADOW_END

Signed-off-by: Lecopzer Chen 
Acked-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
Tested-by: Ard Biesheuvel 
---
 arch/arm64/mm/kasan_init.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index d8e66c78440e..20d06008785f 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
 {
u64 kimg_shadow_start, kimg_shadow_end;
u64 mod_shadow_start, mod_shadow_end;
+   u64 vmalloc_shadow_end;
phys_addr_t pa_start, pa_end;
u64 i;
 
@@ -223,6 +224,8 @@ static void __init kasan_init_shadow(void)
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
 
+   vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END);
+
/*
 * We are going to perform proper setup of shadow memory.
 * At first we should unmap early shadow (clear_pgds() call below).
@@ -241,12 +244,17 @@ static void __init kasan_init_shadow(void)
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-   kasan_populate_early_shadow((void *)kimg_shadow_end,
-  (void *)KASAN_SHADOW_END);
 
-   if (kimg_shadow_start > mod_shadow_end)
-   kasan_populate_early_shadow((void *)mod_shadow_end,
-   (void *)kimg_shadow_start);
+   if (IS_ENABLED(CONFIG_KASAN_VMALLOC))
+   kasan_populate_early_shadow((void *)vmalloc_shadow_end,
+   (void *)KASAN_SHADOW_END);
+   else {
+   kasan_populate_early_shadow((void *)kimg_shadow_end,
+   (void *)KASAN_SHADOW_END);
+   if (kimg_shadow_start > mod_shadow_end)
+   kasan_populate_early_shadow((void *)mod_shadow_end,
+   (void *)kimg_shadow_start);
+   }
 
for_each_mem_range(i, _start, _end) {
void *start = (void *)__phys_to_virt(pa_start);
-- 
2.25.1



[PATCH v4 5/5] arm64: Kconfig: select KASAN_VMALLOC if KANSAN_GENERIC is enabled

2021-03-23 Thread Lecopzer Chen
Before this patch, someone who wants to use VMAP_STACK when
KASAN_GENERIC enabled must explicitly select KASAN_VMALLOC.

>From Will's suggestion [1]:
  > I would _really_ like to move to VMAP stack unconditionally, and
  > that would effectively force KASAN_VMALLOC to be set if KASAN is in use

Because VMAP_STACK now depends on either HW_TAGS or KASAN_VMALLOC if
KASAN enabled, in order to make VMAP_STACK selected unconditionally,
we bind KANSAN_GENERIC and KASAN_VMALLOC together.

Note that SW_TAGS supports neither VMAP_STACK nor KASAN_VMALLOC now,
so this is the first step to make VMAP_STACK selected unconditionally.

Bind KANSAN_GENERIC and KASAN_VMALLOC together is supposed to cost more
memory at runtime, thus the alternative is using SW_TAGS KASAN instead.

[1]: https://lore.kernel.org/lkml/20210204150100.GE20815@willie-the-truck/

Suggested-by: Will Deacon 
Signed-off-by: Lecopzer Chen 
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3e54fa938234..07762359d741 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -195,6 +195,7 @@ config ARM64
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
+   select KASAN_VMALLOC if KASAN_GENERIC
select MODULES_USE_ELF_RELA
select NEED_DMA_MAP_STATE
select NEED_SG_DMA_LENGTH
-- 
2.25.1



[PATCH v4 0/5] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-03-23 Thread Lecopzer Chen


Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Acroding to how x86 ported it [1], they early allocated p4d and pgd,
but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
by not to populate the vmalloc area except for kimg address.

  ---  vmalloc_shadow_start
 |   |
 |   | 
 |   | <= non-mapping
 |   |
 |   |
 |---|
 |///|<- kimage shadow with page table mapping.
 |---|
 |   |
 |   | <= non-mapping
 |   |
 - vmalloc_shadow_end
 |000|
 |000| <= Zero shadow
 |000|
 - KASAN_SHADOW_END


Test environment:
4G and 8G Qemu virt, 
39-bit VA + 4k PAGE_SIZE with 3-level page table,
test by lib/test_kasan.ko and lib/test_kasan_module.ko

It works with Kaslr and CONFIG_RANDOMIZE_MODULE_REGION_FULL
and randomize module region inside vmalloc area.

Also work on VMAP_STACK, thanks Ard for testing it.


[1]: commit 0609ae011deb41c ("x86/kasan: support KASAN_VMALLOC")


---
Thanks Will Deacon, Ard Biesheuvel and Andrey Konovalov
for reviewing and suggestion.

v4:
1. rebase on 5.12-rc4
2. tweak commit message

v3:
rebase on 5.11-rc6
1. remove always true condition in kasan_init() and remove unsed
   vmalloc_shadow_start.
2. select KASAN_VMALLOC if KANSAN_GENERIC is enabled
   for VMAP_STACK.
3. tweak commit message

v2:
1. kasan_init.c tweak indent
2. change Kconfig depends only on HAVE_ARCH_KASAN
3. support randomized module region.



v3:
https://lore.kernel.org/lkml/20210206083552.24394-1-lecopzer.c...@mediatek.com/
v2:
https://lkml.org/lkml/2021/1/9/49
v1:
https://lore.kernel.org/lkml/20210103171137.153834-1-lecop...@gmail.com/
---
Lecopzer Chen (5):
  arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC
  arm64: kasan: abstract _text and _end to KERNEL_START/END
  arm64: Kconfig: support CONFIG_KASAN_VMALLOC
  arm64: kaslr: support randomized module area with KASAN_VMALLOC
  arm64: Kconfig: select KASAN_VMALLOC if KANSAN_GENERIC is enabled

 arch/arm64/Kconfig |  2 ++
 arch/arm64/kernel/kaslr.c  | 18 ++
 arch/arm64/kernel/module.c | 16 +---
 arch/arm64/mm/kasan_init.c | 24 
 4 files changed, 37 insertions(+), 23 deletions(-)

-- 
2.25.1



[PATCH v4 2/5] arm64: kasan: abstract _text and _end to KERNEL_START/END

2021-03-23 Thread Lecopzer Chen
Arm64 provides defined macro for KERNEL_START and KERNEL_END,
thus replace them by the abstration instead of using _text and _end.

Signed-off-by: Lecopzer Chen 
Acked-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
Tested-by: Ard Biesheuvel 
---
 arch/arm64/mm/kasan_init.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 20d06008785f..cd2653b7b174 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -218,8 +218,8 @@ static void __init kasan_init_shadow(void)
phys_addr_t pa_start, pa_end;
u64 i;
 
-   kimg_shadow_start = (u64)kasan_mem_to_shadow(_text) & PAGE_MASK;
-   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(_end));
+   kimg_shadow_start = (u64)kasan_mem_to_shadow(KERNEL_START) & PAGE_MASK;
+   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(KERNEL_END));
 
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
@@ -240,7 +240,7 @@ static void __init kasan_init_shadow(void)
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
 
kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
-  early_pfn_to_nid(virt_to_pfn(lm_alias(_text;
+  
early_pfn_to_nid(virt_to_pfn(lm_alias(KERNEL_START;
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-- 
2.25.1



[PATCH v4 3/5] arm64: Kconfig: support CONFIG_KASAN_VMALLOC

2021-03-23 Thread Lecopzer Chen
We can backed shadow memory in vmalloc area after vmalloc area
isn't populated at kasan_init(), thus make KASAN_VMALLOC selectable.

Signed-off-by: Lecopzer Chen 
Acked-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
Tested-by: Ard Biesheuvel 
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5656e7aacd69..3e54fa938234 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -138,6 +138,7 @@ config ARM64
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
+   select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_HW_TAGS if (HAVE_ARCH_KASAN && ARM64_MTE)
select HAVE_ARCH_KFENCE
-- 
2.25.1



Re: [PATCH v3 1/5] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-03-20 Thread Lecopzer Chen
On Sat, Mar 20, 2021 at 1:38 AM Catalin Marinas  wrote:
>
> On Sat, Feb 06, 2021 at 04:35:48PM +0800, Lecopzer Chen wrote:
> > Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > ("kasan: support backing vmalloc space with real shadow memory")
> >
> > Like how the MODULES_VADDR does now, just not to early populate
> > the VMALLOC_START between VMALLOC_END.
> >
> > Before:
> >
> > MODULE_VADDR: no mapping, no zoreo shadow at init
> > VMALLOC_VADDR: backed with zero shadow at init
> >
> > After:
> >
> > MODULE_VADDR: no mapping, no zoreo shadow at init
> > VMALLOC_VADDR: no mapping, no zoreo shadow at init
>
> s/zoreo/zero/
>

thanks!

> > Thus the mapping will get allocated on demand by the core function
> > of KASAN_VMALLOC.
> >
> >   ---  vmalloc_shadow_start
> >  |   |
> >  |   |
> >  |   | <= non-mapping
> >  |   |
> >  |   |
> >  |---|
> >  |///|<- kimage shadow with page table mapping.
> >  |---|
> >  |   |
> >  |   | <= non-mapping
> >  |   |
> >  - vmalloc_shadow_end
> >  |000|
> >  |000| <= Zero shadow
> >  |000|
> >  - KASAN_SHADOW_END
> >
> > Signed-off-by: Lecopzer Chen 
> > ---
> >  arch/arm64/mm/kasan_init.c | 18 +-
> >  1 file changed, 13 insertions(+), 5 deletions(-)
> >
> > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> > index d8e66c78440e..20d06008785f 100644
> > --- a/arch/arm64/mm/kasan_init.c
> > +++ b/arch/arm64/mm/kasan_init.c
> > @@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
> >  {
> >   u64 kimg_shadow_start, kimg_shadow_end;
> >   u64 mod_shadow_start, mod_shadow_end;
> > + u64 vmalloc_shadow_end;
> >   phys_addr_t pa_start, pa_end;
> >   u64 i;
> >
> > @@ -223,6 +224,8 @@ static void __init kasan_init_shadow(void)
> >   mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
> >   mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
> >
> > + vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END);
> > +
> >   /*
> >* We are going to perform proper setup of shadow memory.
> >* At first we should unmap early shadow (clear_pgds() call below).
> > @@ -241,12 +244,17 @@ static void __init kasan_init_shadow(void)
> >
> >   kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
> >  (void *)mod_shadow_start);
> > - kasan_populate_early_shadow((void *)kimg_shadow_end,
> > -(void *)KASAN_SHADOW_END);
> >
> > - if (kimg_shadow_start > mod_shadow_end)
> > - kasan_populate_early_shadow((void *)mod_shadow_end,
> > - (void *)kimg_shadow_start);
>
> Not something introduced by this patch but what happens if this
> condition is false? It means that kimg_shadow_end < mod_shadow_start and
> the above kasan_populate_early_shadow(PAGE_END, mod_shadow_start)
> overlaps with the earlier kasan_map_populate(kimg_shadow_start,
> kimg_shadow_end).

In this case, the area between mod_shadow_start and kimg_shadow_end
was mapping when kasan init.

Thus the corner case is that module_alloc() allocates that range
(the area between mod_shadow_start and kimg_shadow_end) again.


With VMALLOC_KASAN,
module_alloc() ->
... ->
kasan_populate_vmalloc ->
apply_to_page_range()
will check the mapping exists or not and bypass allocating new mapping
if it exists.
So it should be fine in the second allocation.

Without VMALLOC_KASAN,
module_alloc() ->
kasan_module_alloc()
will allocate the range twice, first time is kasan_map_populate() and
second time is vmalloc(),
and this should have some problems(?).

Now the only possibility that the module area can overlap with kimage
should be KASLR on.
I'm not sure if this is the case that really happens in KASLR, it depends on
how __relocate_kernel() calculates kimage and how kaslr_earlt_init()
decides module_alloc_base.


> > + if (IS_ENABLED(CONFIG_KASAN_VMALLOC))
> > + kasan_populate_early_shadow((void *)vmalloc_shadow_end,
> > + (void *)KASAN_SHADOW_END);
> > + else {
> > + kasan_populate_early_shadow((void *)kimg_shadow_end,
> > + (void *)KASAN_SHADOW_END);
> > + if (kimg_shadow_start > mod_shadow_end)
> > + kasan_populate_early_shadow((void *)mod_shadow_end,
> > + (void 
> > *)kimg_shadow_start);
> > + }
> >
> >   for_each_mem_range(i, _start, _end) {
> >   void *start = (void *)__phys_to_virt(pa_start);
> > --
> > 2.25.1
> >


Re: [PATCH v3 0/5] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-03-20 Thread Lecopzer Chen
On Sat, Mar 20, 2021 at 1:41 AM Catalin Marinas  wrote:
>
> Hi Lecopzer,
>
> On Sat, Feb 06, 2021 at 04:35:47PM +0800, Lecopzer Chen wrote:
> > Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > ("kasan: support backing vmalloc space with real shadow memory")
> >
> > Acroding to how x86 ported it [1], they early allocated p4d and pgd,
> > but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
> > by not to populate the vmalloc area except for kimg address.
>
> Do you plan an update to a newer kernel like 5.12-rc3?
>

Yes, of course. I dealt with some personal matters so didn't update
these series last month.

> > Signed-off-by: Lecopzer Chen 
> > Acked-by: Andrey Konovalov 
> > Tested-by: Andrey Konovalov 
> > Tested-by: Ard Biesheuvel 
>
> You could move these to individual patches rather than the cover letter,
> assuming that they still stand after the changes you've made. Also note
> that Andrey K no longer has the @google.com email address if you cc him
> on future patches (replace it with @gmail.com).
>

Ok thanks for the suggestion.
I will move them to each patch and correct the email address.


Thanks,
Lecopzer


[PATCH v3 5/5] arm64: Kconfig: select KASAN_VMALLOC if KANSAN_GENERIC is enabled

2021-02-06 Thread Lecopzer Chen
Before this patch, someone who wants to use VMAP_STACK when
KASAN_GENERIC enabled must explicitly select KASAN_VMALLOC.

>From Will's suggestion [1]:
  > I would _really_ like to move to VMAP stack unconditionally, and
  > that would effectively force KASAN_VMALLOC to be set if KASAN is in use.

Because VMAP_STACK now depends on either HW_TAGS or KASAN_VMALLOC if
KASAN enabled, in order to make VMAP_STACK selected unconditionally,
we bind KANSAN_GENERIC and KASAN_VMALLOC together.

Note that SW_TAGS supports neither VMAP_STACK nor KASAN_VMALLOC now,
so this is the first step to make VMAP_STACK selected unconditionally.

Bind KANSAN_GENERIC and KASAN_VMALLOC together is supposed to cost more
memory at runtime, thus the alternative is using SW_TAGS KASAN instead.

[1]: https://lore.kernel.org/lkml/20210204150100.GE20815@willie-the-truck/

Suggested-by: Will Deacon 
Signed-off-by: Lecopzer Chen 
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a8f5a9171a85..9be6a57f6447 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -190,6 +190,7 @@ config ARM64
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
select IRQ_FORCED_THREADING
+   select KASAN_VMALLOC if KASAN_GENERIC
select MODULES_USE_ELF_RELA
select NEED_DMA_MAP_STATE
select NEED_SG_DMA_LENGTH
-- 
2.25.1



[PATCH v3 0/5] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-02-06 Thread Lecopzer Chen


Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Acroding to how x86 ported it [1], they early allocated p4d and pgd,
but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
by not to populate the vmalloc area except for kimg address.

  ---  vmalloc_shadow_start
 |   |
 |   | 
 |   | <= non-mapping
 |   |
 |   |
 |---|
 |///|<- kimage shadow with page table mapping.
 |---|
 |   |
 |   | <= non-mapping
 |   |
 - vmalloc_shadow_end
 |000|
 |000| <= Zero shadow
 |000|
 - KASAN_SHADOW_END


Test environment:
4G and 8G Qemu virt, 
39-bit VA + 4k PAGE_SIZE with 3-level page table,
test by lib/test_kasan.ko and lib/test_kasan_module.ko

It works in Kaslr with CONFIG_RANDOMIZE_MODULE_REGION_FULL
and randomize module region inside vmalloc area.

Also work with VMAP_STACK, thanks Ard for testing it.


[1]: commit 0609ae011deb41c ("x86/kasan: support KASAN_VMALLOC")


Signed-off-by: Lecopzer Chen 
Acked-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 
Tested-by: Ard Biesheuvel 

---
Thanks Will Deacon, Ard Biesheuvel and Andrey Konovalov
for reviewing and suggestion.

v3 -> v2
rebase on 5.11-rc6
1. remove always true condition in kasan_init() and remove unsed
   vmalloc_shadow_start.
2. select KASAN_VMALLOC if KANSAN_GENERIC is enabled
   for VMAP_STACK.
3. tweak commit message

v2 -> v1
1. kasan_init.c tweak indent
2. change Kconfig depends only on HAVE_ARCH_KASAN
3. support randomized module region.


v2:
https://lkml.org/lkml/2021/1/9/49
v1:
https://lore.kernel.org/lkml/20210103171137.153834-1-lecop...@gmail.com/
---
Lecopzer Chen (5):
  arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC
  arm64: kasan: abstract _text and _end to KERNEL_START/END
  arm64: Kconfig: support CONFIG_KASAN_VMALLOC
  arm64: kaslr: support randomized module area with KASAN_VMALLOC
  arm64: Kconfig: select KASAN_VMALLOC if KANSAN_GENERIC is enabled

 arch/arm64/Kconfig |  2 ++
 arch/arm64/kernel/kaslr.c  | 18 ++
 arch/arm64/kernel/module.c | 16 +---
 arch/arm64/mm/kasan_init.c | 24 
 4 files changed, 37 insertions(+), 23 deletions(-)

-- 
2.25.1



[PATCH v3 3/5] arm64: Kconfig: support CONFIG_KASAN_VMALLOC

2021-02-06 Thread Lecopzer Chen
Now we can backed shadow memory in vmalloc area,
thus make KASAN_VMALLOC selectable.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index f39568b28ec1..a8f5a9171a85 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -136,6 +136,7 @@ config ARM64
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
+   select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_HW_TAGS if (HAVE_ARCH_KASAN && ARM64_MTE)
select HAVE_ARCH_KGDB
-- 
2.25.1



[PATCH v3 4/5] arm64: kaslr: support randomized module area with KASAN_VMALLOC

2021-02-06 Thread Lecopzer Chen
After KASAN_VMALLOC works in arm64, we can randomize module region
into vmalloc area now.

Test:
VMALLOC area ffc01000 fffdf000

before the patch:
module_alloc_base/end ffc008b8 ffc01000
after the patch:
module_alloc_base/end ffdcf4bed000 ffc01000

And the function that insmod some modules is fine.

Suggested-by: Ard Biesheuvel 
Signed-off-by: Lecopzer Chen 
---
 arch/arm64/kernel/kaslr.c  | 18 ++
 arch/arm64/kernel/module.c | 16 +---
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
index 1c74c45b9494..a2858058e724 100644
--- a/arch/arm64/kernel/kaslr.c
+++ b/arch/arm64/kernel/kaslr.c
@@ -161,15 +161,17 @@ u64 __init kaslr_early_init(u64 dt_phys)
/* use the top 16 bits to randomize the linear region */
memstart_offset_seed = seed >> 48;
 
-   if (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
-   IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+   if (!IS_ENABLED(CONFIG_KASAN_VMALLOC) &&
+   (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
+IS_ENABLED(CONFIG_KASAN_SW_TAGS)))
/*
-* KASAN does not expect the module region to intersect the
-* vmalloc region, since shadow memory is allocated for each
-* module at load time, whereas the vmalloc region is shadowed
-* by KASAN zero pages. So keep modules out of the vmalloc
-* region if KASAN is enabled, and put the kernel well within
-* 4 GB of the module region.
+* KASAN without KASAN_VMALLOC does not expect the module region
+* to intersect the vmalloc region, since shadow memory is
+* allocated for each module at load time, whereas the vmalloc
+* region is shadowed by KASAN zero pages. So keep modules
+* out of the vmalloc region if KASAN is enabled without
+* KASAN_VMALLOC, and put the kernel well within 4 GB of the
+* module region.
 */
return offset % SZ_2G;
 
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index fe21e0f06492..b5ec010c481f 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -40,14 +40,16 @@ void *module_alloc(unsigned long size)
NUMA_NO_NODE, __builtin_return_address(0));
 
if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
-   !IS_ENABLED(CONFIG_KASAN_GENERIC) &&
-   !IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+   (IS_ENABLED(CONFIG_KASAN_VMALLOC) ||
+(!IS_ENABLED(CONFIG_KASAN_GENERIC) &&
+ !IS_ENABLED(CONFIG_KASAN_SW_TAGS
/*
-* KASAN can only deal with module allocations being served
-* from the reserved module region, since the remainder of
-* the vmalloc region is already backed by zero shadow pages,
-* and punching holes into it is non-trivial. Since the module
-* region is not randomized when KASAN is enabled, it is even
+* KASAN without KASAN_VMALLOC can only deal with module
+* allocations being served from the reserved module region,
+* since the remainder of the vmalloc region is already
+* backed by zero shadow pages, and punching holes into it
+* is non-trivial. Since the module region is not randomized
+* when KASAN is enabled without KASAN_VMALLOC, it is even
 * less likely that the module region gets exhausted, so we
 * can simply omit this fallback in that case.
 */
-- 
2.25.1



[PATCH v3 2/5] arm64: kasan: abstract _text and _end to KERNEL_START/END

2021-02-06 Thread Lecopzer Chen
Arm64 provides defined macro for KERNEL_START and KERNEL_END,
thus replace them by the abstration instead of using _text and _end.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/mm/kasan_init.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 20d06008785f..cd2653b7b174 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -218,8 +218,8 @@ static void __init kasan_init_shadow(void)
phys_addr_t pa_start, pa_end;
u64 i;
 
-   kimg_shadow_start = (u64)kasan_mem_to_shadow(_text) & PAGE_MASK;
-   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(_end));
+   kimg_shadow_start = (u64)kasan_mem_to_shadow(KERNEL_START) & PAGE_MASK;
+   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(KERNEL_END));
 
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
@@ -240,7 +240,7 @@ static void __init kasan_init_shadow(void)
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
 
kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
-  early_pfn_to_nid(virt_to_pfn(lm_alias(_text;
+  
early_pfn_to_nid(virt_to_pfn(lm_alias(KERNEL_START;
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-- 
2.25.1



[PATCH v3 1/5] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-02-06 Thread Lecopzer Chen
Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Like how the MODULES_VADDR does now, just not to early populate
the VMALLOC_START between VMALLOC_END.

Before:

MODULE_VADDR: no mapping, no zoreo shadow at init
VMALLOC_VADDR: backed with zero shadow at init

After:

MODULE_VADDR: no mapping, no zoreo shadow at init
VMALLOC_VADDR: no mapping, no zoreo shadow at init

Thus the mapping will get allocated on demand by the core function
of KASAN_VMALLOC.

  ---  vmalloc_shadow_start
 |   |
 |   |
 |   | <= non-mapping
 |   |
 |   |
 |---|
 |///|<- kimage shadow with page table mapping.
 |---|
 |   |
 |   | <= non-mapping
 |   |
 - vmalloc_shadow_end
 |000|
 |000| <= Zero shadow
 |000|
 - KASAN_SHADOW_END

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/mm/kasan_init.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index d8e66c78440e..20d06008785f 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
 {
u64 kimg_shadow_start, kimg_shadow_end;
u64 mod_shadow_start, mod_shadow_end;
+   u64 vmalloc_shadow_end;
phys_addr_t pa_start, pa_end;
u64 i;
 
@@ -223,6 +224,8 @@ static void __init kasan_init_shadow(void)
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
 
+   vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END);
+
/*
 * We are going to perform proper setup of shadow memory.
 * At first we should unmap early shadow (clear_pgds() call below).
@@ -241,12 +244,17 @@ static void __init kasan_init_shadow(void)
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-   kasan_populate_early_shadow((void *)kimg_shadow_end,
-  (void *)KASAN_SHADOW_END);
 
-   if (kimg_shadow_start > mod_shadow_end)
-   kasan_populate_early_shadow((void *)mod_shadow_end,
-   (void *)kimg_shadow_start);
+   if (IS_ENABLED(CONFIG_KASAN_VMALLOC))
+   kasan_populate_early_shadow((void *)vmalloc_shadow_end,
+   (void *)KASAN_SHADOW_END);
+   else {
+   kasan_populate_early_shadow((void *)kimg_shadow_end,
+   (void *)KASAN_SHADOW_END);
+   if (kimg_shadow_start > mod_shadow_end)
+   kasan_populate_early_shadow((void *)mod_shadow_end,
+   (void *)kimg_shadow_start);
+   }
 
for_each_mem_range(i, _start, _end) {
void *start = (void *)__phys_to_virt(pa_start);
-- 
2.25.1



Re: [PATCH v2 1/4] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-02-05 Thread Lecopzer Chen
Will Deacon  於 2021年2月6日 週六 上午1:19寫道:
>
> On Fri, Feb 05, 2021 at 12:37:21AM +0800, Lecopzer Chen wrote:
> >
> > > On Thu, Feb 04, 2021 at 10:46:12PM +0800, Lecopzer Chen wrote:
> > > > > On Sat, Jan 09, 2021 at 06:32:49PM +0800, Lecopzer Chen wrote:
> > > > > > Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > > > > > ("kasan: support backing vmalloc space with real shadow memory")
> > > > > >
> > > > > > Like how the MODULES_VADDR does now, just not to early populate
> > > > > > the VMALLOC_START between VMALLOC_END.
> > > > > > similarly, the kernel code mapping is now in the VMALLOC area and
> > > > > > should keep these area populated.
> > > > > >
> > > > > > Signed-off-by: Lecopzer Chen 
> > > > > > ---
> > > > > >  arch/arm64/mm/kasan_init.c | 23 ++-
> > > > > >  1 file changed, 18 insertions(+), 5 deletions(-)
> > > > > >
> > > > > > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> > > > > > index d8e66c78440e..39b218a64279 100644
> > > > > > --- a/arch/arm64/mm/kasan_init.c
> > > > > > +++ b/arch/arm64/mm/kasan_init.c
> > > > > > @@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
> > > > > >  {
> > > > > >   u64 kimg_shadow_start, kimg_shadow_end;
> > > > > >   u64 mod_shadow_start, mod_shadow_end;
> > > > > > + u64 vmalloc_shadow_start, vmalloc_shadow_end;
> > > > > >   phys_addr_t pa_start, pa_end;
> > > > > >   u64 i;
> > > > > >
> > > > > > @@ -223,6 +224,9 @@ static void __init kasan_init_shadow(void)
> > > > > >   mod_shadow_start = (u64)kasan_mem_to_shadow((void 
> > > > > > *)MODULES_VADDR);
> > > > > >   mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
> > > > > >
> > > > > > + vmalloc_shadow_start = (u64)kasan_mem_to_shadow((void 
> > > > > > *)VMALLOC_START);
> > > > > > + vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void 
> > > > > > *)VMALLOC_END);
> > > > > > +
> > > > > >   /*
> > > > > >* We are going to perform proper setup of shadow memory.
> > > > > >* At first we should unmap early shadow (clear_pgds() call 
> > > > > > below).
> > > > > > @@ -241,12 +245,21 @@ static void __init kasan_init_shadow(void)
> > > > > >
> > > > > >   kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
> > > > > >  (void *)mod_shadow_start);
> > > > > > - kasan_populate_early_shadow((void *)kimg_shadow_end,
> > > > > > -(void *)KASAN_SHADOW_END);
> > > > > > + if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
> > > > >
> > > > > Do we really need yet another CONFIG option for KASAN? What's the 
> > > > > use-case
> > > > > for *not* enabling this if you're already enabling one of the KASAN
> > > > > backends?
> > > >commit message
> > > > As I know, KASAN_VMALLOC now only supports KASAN_GENERIC and also
> > > > KASAN_VMALLOC uses more memory to map real shadow memory (1/8 of 
> > > > vmalloc va).
> > >
> > > The shadow is allocated dynamically though, isn't it?
> >
> > Yes, but It's still a cost.
> >
> > > > There should be someone can enable KASAN_GENERIC but can't use VMALLOC
> > > > due to memory issue.
> > >
> > > That doesn't sound particularly realistic to me. The reason I'm pushing 
> > > here
> > > is because I would _really_ like to move to VMAP stack unconditionally, 
> > > and
> > > that would effectively force KASAN_VMALLOC to be set if KASAN is in use.
> > >
> > > So unless there's a really good reason not to do that, please can we make
> > > this unconditional for arm64? Pretty please?
> >
> > I think it's fine since we have a good reason.
> > Also if someone have memory issue in KASAN_VMALLOC,
> > they can use SW_TAG, right?
> >
> > However the SW_TAG/HW_TAG is not supported VMALLOC yet.
> > So the code would be like
> >
> >   if (IS_ENABLED(CONFIG_KASAN_GENERIC))
>
> Just make this CONFIG_KASAN_VMALLOC, since that depends on KASAN_GENERIC.

OK, this also make sense.
My first thought was that selecting KASAN_GENERIC implies VMALLOC in
arm64 is a special case so this need well documented.
I'll document this in the commit message of Kconfig patch to avoid
messing up the code here.

I'm going to send V3 patch, thanks again for your review.

BRs,
Lecopzer


Re: [PATCH v2 0/4] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-02-04 Thread Lecopzer Chen
> On Thu, Feb 04, 2021 at 11:53:46PM +0800, Lecopzer Chen wrote:
> > > On Sat, Jan 09, 2021 at 06:32:48PM +0800, Lecopzer Chen wrote:
> > > > Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > > > ("kasan: support backing vmalloc space with real shadow memory")
> > > >
> > > > Acroding to how x86 ported it [1], they early allocated p4d and pgd,
> > > > but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
> > > > by not to populate the vmalloc area except for kimg address.
> > >
> > > The one thing I've failed to grok from your series is how you deal with
> > > vmalloc allocations where the shadow overlaps with the shadow which has
> > > already been allocated for the kernel image. Please can you explain?
> >
> >
> > The most key point is we don't map anything in the vmalloc shadow address.
> > So we don't care where the kernel image locate inside vmalloc area.
> >
> >   kasan_map_populate(kimg_shadow_start, kimg_shadow_end,...)
> >
> > Kernel image was populated with real mapping in its shadow address.
> > I `bypass' the whole shadow of vmalloc area, the only place you can find
> > about vmalloc_shadow is
> >   kasan_populate_early_shadow((void *)vmalloc_shadow_end,
> >   (void *)KASAN_SHADOW_END);
> >
> >   ---  vmalloc_shadow_start
> >  |   |
> >  |   |
> >  |   | <= non-mapping
> >  |   |
> >  |   |
> >  |---|
> >  |///|<- kimage shadow with page table mapping.
> >  |---|
> >  |   |
> >  |   | <= non-mapping
> >  |   |
> >  - vmalloc_shadow_end
> >  |000|
> >  |000| <= Zero shadow
> >  |000|
> >  - KASAN_SHADOW_END
> >
> > vmalloc shadow will be mapped 'ondemend', see kasan_populate_vmalloc()
> > in mm/vmalloc.c in detail.
> > So the shadow of vmalloc will be allocated later if anyone use its va.
>
> Indeed, but the question I'm asking is what happens when an on-demand shadow
> allocation from vmalloc overlaps with the shadow that we allocated early for
> the kernel image?
>
> Sounds like I have to go and read the code...
oh, sorry I misunderstood your question.

FWIW,
I think this won't happend because this mean vmalloc() provides va
which already allocated by kimg, as I know, vmalloc_init() will insert
early allocated vma into its vmalloc rb tree

, and this early allocated vma will include  kernel image.

After quick review of mm init code,
this early allocated for vma is at map_kernel() in arch/arm64/mm/mmu.c



BRs
Lecopzer


Re: [PATCH v2 1/4] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-02-04 Thread Lecopzer Chen


> On Thu, Feb 04, 2021 at 10:46:12PM +0800, Lecopzer Chen wrote:
> > > On Sat, Jan 09, 2021 at 06:32:49PM +0800, Lecopzer Chen wrote:
> > > > Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > > > ("kasan: support backing vmalloc space with real shadow memory")
> > > >
> > > > Like how the MODULES_VADDR does now, just not to early populate
> > > > the VMALLOC_START between VMALLOC_END.
> > > > similarly, the kernel code mapping is now in the VMALLOC area and
> > > > should keep these area populated.
> > > >
> > > > Signed-off-by: Lecopzer Chen 
> > > > ---
> > > >  arch/arm64/mm/kasan_init.c | 23 ++-
> > > >  1 file changed, 18 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> > > > index d8e66c78440e..39b218a64279 100644
> > > > --- a/arch/arm64/mm/kasan_init.c
> > > > +++ b/arch/arm64/mm/kasan_init.c
> > > > @@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
> > > >  {
> > > >   u64 kimg_shadow_start, kimg_shadow_end;
> > > >   u64 mod_shadow_start, mod_shadow_end;
> > > > + u64 vmalloc_shadow_start, vmalloc_shadow_end;
> > > >   phys_addr_t pa_start, pa_end;
> > > >   u64 i;
> > > >
> > > > @@ -223,6 +224,9 @@ static void __init kasan_init_shadow(void)
> > > >   mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
> > > >   mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
> > > >
> > > > + vmalloc_shadow_start = (u64)kasan_mem_to_shadow((void 
> > > > *)VMALLOC_START);
> > > > + vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END);
> > > > +
> > > >   /*
> > > >    * We are going to perform proper setup of shadow memory.
> > > >    * At first we should unmap early shadow (clear_pgds() call below).
> > > > @@ -241,12 +245,21 @@ static void __init kasan_init_shadow(void)
> > > >
> > > >   kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
> > > >                              (void *)mod_shadow_start);
> > > > - kasan_populate_early_shadow((void *)kimg_shadow_end,
> > > > -                            (void *)KASAN_SHADOW_END);
> > > > + if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
> > >
> > > Do we really need yet another CONFIG option for KASAN? What's the use-case
> > > for *not* enabling this if you're already enabling one of the KASAN
> > > backends?
> >
> > As I know, KASAN_VMALLOC now only supports KASAN_GENERIC and also
> > KASAN_VMALLOC uses more memory to map real shadow memory (1/8 of vmalloc 
> > va).
>
> The shadow is allocated dynamically though, isn't it?

Yes, but It's still a cost.

> > There should be someone can enable KASAN_GENERIC but can't use VMALLOC
> > due to memory issue.
>
> That doesn't sound particularly realistic to me. The reason I'm pushing here
> is because I would _really_ like to move to VMAP stack unconditionally, and
> that would effectively force KASAN_VMALLOC to be set if KASAN is in use.
>
> So unless there's a really good reason not to do that, please can we make
> this unconditional for arm64? Pretty please?

I think it's fine since we have a good reason.
Also if someone have memory issue in KASAN_VMALLOC,
they can use SW_TAG, right?

However the SW_TAG/HW_TAG is not supported VMALLOC yet.
So the code would be like

if (IS_ENABLED(CONFIG_KASAN_GENERIC))
/* explain the relationship between 
 * KASAN_GENERIC and KASAN_VMALLOC in arm64
 * XXX: because we want VMAP stack
 */
kasan_populate_early_shadow((void *)vmalloc_shadow_end,
(void *)KASAN_SHADOW_END);
else {
kasan_populate_early_shadow((void *)kimg_shadow_end,
(void *)KASAN_SHADOW_END);
if (kimg_shadow_start > mod_shadow_end)
kasan_populate_early_shadow((void *)mod_shadow_end,
(void *)kimg_shadow_start);
}

and the arch/arm64/Kconfig will add
select KASAN_VMALLOC if KASAN_GENERIC

Is this code same as your thought?

BRs,
Lecopzer



Re: [PATCH v2 2/4] arm64: kasan: abstract _text and _end to KERNEL_START/END

2021-02-04 Thread Lecopzer Chen
I think it would be better to leave this for you since I'm not
familiar with the relationship
between vmemmap() and NUMA_NO_NODE.

So I would just keep this patch in next version, is this fine with you?


Thanks for your help:)

Lecopzer



Will Deacon  於 2021年2月4日 週四 下午10:55寫道:
>
> On Thu, Feb 04, 2021 at 10:51:27PM +0800, Lecopzer Chen wrote:
> > > On Sat, Jan 09, 2021 at 06:32:50PM +0800, Lecopzer Chen wrote:
> > > > Arm64 provide defined macro for KERNEL_START and KERNEL_END,
> > > > thus replace them by the abstration instead of using _text and _end.
> > > >
> > > > Signed-off-by: Lecopzer Chen 
> > > > ---
> > > >  arch/arm64/mm/kasan_init.c | 6 +++---
> > > >  1 file changed, 3 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> > > > index 39b218a64279..fa8d7ece895d 100644
> > > > --- a/arch/arm64/mm/kasan_init.c
> > > > +++ b/arch/arm64/mm/kasan_init.c
> > > > @@ -218,8 +218,8 @@ static void __init kasan_init_shadow(void)
> > > >   phys_addr_t pa_start, pa_end;
> > > >   u64 i;
> > > >
> > > > - kimg_shadow_start = (u64)kasan_mem_to_shadow(_text) & PAGE_MASK;
> > > > - kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(_end));
> > > > + kimg_shadow_start = (u64)kasan_mem_to_shadow(KERNEL_START) & 
> > > > PAGE_MASK;
> > > > + kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(KERNEL_END));
> > > >
> > > >   mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
> > > >   mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
> > > > @@ -241,7 +241,7 @@ static void __init kasan_init_shadow(void)
> > > >   clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
> > > >
> > > >   kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
> > > > -early_pfn_to_nid(virt_to_pfn(lm_alias(_text;
> > > > +
> > > > early_pfn_to_nid(virt_to_pfn(lm_alias(KERNEL_START;
> > >
> > > To be honest, I think this whole line is pointless. We should be able to
> > > pass NUMA_NO_NODE now that we're not abusing the vmemmap() allocator to
> > > populate the shadow.
> >
> > Do we need to fix this in this series? it seems another topic.
> > If not, should this patch be removed in this series?
>
> Since you're reposting anyway, you may as well include a patch doing that.
> If you don't, then I will.
>
> Will


Re: [PATCH v2 0/4] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-02-04 Thread Lecopzer Chen
> On Sat, Jan 09, 2021 at 06:32:48PM +0800, Lecopzer Chen wrote:
> > Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > ("kasan: support backing vmalloc space with real shadow memory")
> > 
> > Acroding to how x86 ported it [1], they early allocated p4d and pgd,
> > but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
> > by not to populate the vmalloc area except for kimg address.
> 
> The one thing I've failed to grok from your series is how you deal with
> vmalloc allocations where the shadow overlaps with the shadow which has
> already been allocated for the kernel image. Please can you explain?


The most key point is we don't map anything in the vmalloc shadow address.
So we don't care where the kernel image locate inside vmalloc area.

  kasan_map_populate(kimg_shadow_start, kimg_shadow_end,...)

Kernel image was populated with real mapping in its shadow address.
I `bypass' the whole shadow of vmalloc area, the only place you can find
about vmalloc_shadow is
kasan_populate_early_shadow((void *)vmalloc_shadow_end,
(void *)KASAN_SHADOW_END);

---  vmalloc_shadow_start
 |   |
 |   | 
 |   | <= non-mapping
 |   |
 |   |
 |---|
 |///|<- kimage shadow with page table mapping.
 |---|
 |   |
 |   | <= non-mapping
 |   |
 - vmalloc_shadow_end
 |000|
 |000| <= Zero shadow
 |000|
 - KASAN_SHADOW_END

vmalloc shadow will be mapped 'ondemend', see kasan_populate_vmalloc()
in mm/vmalloc.c in detail.
So the shadow of vmalloc will be allocated later if anyone use its va.


BRs,
Lecopzer




Re: [PATCH v2 2/4] arm64: kasan: abstract _text and _end to KERNEL_START/END

2021-02-04 Thread Lecopzer Chen
> On Sat, Jan 09, 2021 at 06:32:50PM +0800, Lecopzer Chen wrote:
> > Arm64 provide defined macro for KERNEL_START and KERNEL_END,
> > thus replace them by the abstration instead of using _text and _end.
> > 
> > Signed-off-by: Lecopzer Chen 
> > ---
> >  arch/arm64/mm/kasan_init.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> > index 39b218a64279..fa8d7ece895d 100644
> > --- a/arch/arm64/mm/kasan_init.c
> > +++ b/arch/arm64/mm/kasan_init.c
> > @@ -218,8 +218,8 @@ static void __init kasan_init_shadow(void)
> > phys_addr_t pa_start, pa_end;
> > u64 i;
> >  
> > -   kimg_shadow_start = (u64)kasan_mem_to_shadow(_text) & PAGE_MASK;
> > -   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(_end));
> > +   kimg_shadow_start = (u64)kasan_mem_to_shadow(KERNEL_START) & PAGE_MASK;
> > +   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(KERNEL_END));
> >  
> > mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
> > mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
> > @@ -241,7 +241,7 @@ static void __init kasan_init_shadow(void)
> > clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
> >  
> > kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
> > -  early_pfn_to_nid(virt_to_pfn(lm_alias(_text;
> > +  
> > early_pfn_to_nid(virt_to_pfn(lm_alias(KERNEL_START;
> 
> To be honest, I think this whole line is pointless. We should be able to
> pass NUMA_NO_NODE now that we're not abusing the vmemmap() allocator to
> populate the shadow.

Do we need to fix this in this series? it seems another topic.
If not, should this patch be removed in this series?

Thanks,
Lecopzer


Re: [PATCH v2 1/4] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-02-04 Thread Lecopzer Chen
> On Sat, Jan 09, 2021 at 06:32:49PM +0800, Lecopzer Chen wrote:
> > Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > ("kasan: support backing vmalloc space with real shadow memory")
> > 
> > Like how the MODULES_VADDR does now, just not to early populate
> > the VMALLOC_START between VMALLOC_END.
> > similarly, the kernel code mapping is now in the VMALLOC area and
> > should keep these area populated.
> > 
> > Signed-off-by: Lecopzer Chen 
> > ---
> >  arch/arm64/mm/kasan_init.c | 23 ++-
> >  1 file changed, 18 insertions(+), 5 deletions(-)
> > 
> > diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
> > index d8e66c78440e..39b218a64279 100644
> > --- a/arch/arm64/mm/kasan_init.c
> > +++ b/arch/arm64/mm/kasan_init.c
> > @@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
> >  {
> > u64 kimg_shadow_start, kimg_shadow_end;
> > u64 mod_shadow_start, mod_shadow_end;
> > +   u64 vmalloc_shadow_start, vmalloc_shadow_end;
> > phys_addr_t pa_start, pa_end;
> > u64 i;
> >  
> > @@ -223,6 +224,9 @@ static void __init kasan_init_shadow(void)
> > mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
> > mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
> >  
> > +   vmalloc_shadow_start = (u64)kasan_mem_to_shadow((void *)VMALLOC_START);
> > +   vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END);
> > +
> > /*
> >  * We are going to perform proper setup of shadow memory.
> >  * At first we should unmap early shadow (clear_pgds() call below).
> > @@ -241,12 +245,21 @@ static void __init kasan_init_shadow(void)
> >  
> > kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
> >(void *)mod_shadow_start);
> > -   kasan_populate_early_shadow((void *)kimg_shadow_end,
> > -  (void *)KASAN_SHADOW_END);
> > +   if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
> 
> Do we really need yet another CONFIG option for KASAN? What's the use-case
> for *not* enabling this if you're already enabling one of the KASAN
> backends?

As I know, KASAN_VMALLOC now only supports KASAN_GENERIC and also
KASAN_VMALLOC uses more memory to map real shadow memory (1/8 of vmalloc va).

There should be someone can enable KASAN_GENERIC but can't use VMALLOC
due to memory issue.
 
> > +   kasan_populate_early_shadow((void *)vmalloc_shadow_end,
> > +   (void *)KASAN_SHADOW_END);
> > +   if (vmalloc_shadow_start > mod_shadow_end)
> 
> To echo Ard's concern: when is the above 'if' condition true?

After reviewing this code,
since VMALLOC_STAR is a compiler defined macro of MODULES_END,
this if-condition will never be true.

I also test it with removing this and works fine.

I'll remove this in the next version patch,
thanks a lot for pointing out this.

BRs,
Lecopzer


Re: [PATCH v2 1/4] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-02-03 Thread Lecopzer Chen
> On Sat, 9 Jan 2021 at 11:33, Lecopzer Chen  wrote:
> >
> > Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > ("kasan: support backing vmalloc space with real shadow memory")
> >
> > Like how the MODULES_VADDR does now, just not to early populate
> > the VMALLOC_START between VMALLOC_END.
> > similarly, the kernel code mapping is now in the VMALLOC area and
> > should keep these area populated.
> >
> > Signed-off-by: Lecopzer Chen 
> 
> 
> This commit log text is a bit hard to follow. You are saying that the
> vmalloc region is *not* backed with zero shadow or any default mapping
> at all, right, and everything gets allocated on demand, just like is
> the case for modules?

It's much more like:

before:

MODULE_VADDR: no mapping, no zoreo shadow at init
VMALLOC_VADDR: backed with zero shadow at init

after:

MODULE_VADDR: no mapping, no zoreo shadow at init
VMALLOC_VADDR: no mapping, no zoreo shadow at init

So it should be both "not backed with zero shadow" and
"not any mapping and everything gets allocated on demand".

And the "not backed with zero shadow" is like a subset of "not any mapping ...".


Is that being more clear if the commit revises to:

--
Like how the MODULES_VADDR does now, just not to early populate
the VMALLOC_START between VMALLOC_END.

Before:

MODULE_VADDR: no mapping, no zoreo shadow at init
VMALLOC_VADDR: backed with zero shadow at init

After:

VMALLOC_VADDR: no mapping, no zoreo shadow at init

Thus the mapping will get allocate on demand by the core function
of KASAN vmalloc.

similarly, the kernel code mapping is now in the VMALLOC area and
should keep these area populated.


Or would you have any suggestion?


Thanks a lot for your review!

BRs,
Lecopzer



Re: [PATCH v8 07/14] mm: honor PF_MEMALLOC_PIN for all movable pages

2021-01-31 Thread Lecopzer Chen


Hi,

[...]
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index c93e801a45e9..3f17c73ad582 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -3807,16 +3807,13 @@ alloc_flags_nofragment(struct zone *zone, gfp_t 
> gfp_mask)
>   return alloc_flags;
>  }
>  
> -static inline unsigned int current_alloc_flags(gfp_t gfp_mask,
> - unsigned int alloc_flags)
> +/* Must be called after current_gfp_context() which can change gfp_mask */
> +static inline unsigned int gpf_to_alloc_flags(gfp_t gfp_mask,
> +   unsigned int alloc_flags)
>  {
>  #ifdef CONFIG_CMA
> - unsigned int pflags = current->flags;
> -
> - if (!(pflags & PF_MEMALLOC_PIN) &&
> - gfp_migratetype(gfp_mask) == MIGRATE_MOVABLE)
> + if (gfp_migratetype(gfp_mask) == MIGRATE_MOVABLE)
>   alloc_flags |= ALLOC_CMA;
> -
>  #endif
>   return alloc_flags;
>  }
> @@ -4472,7 +4469,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask)
>   } else if (unlikely(rt_task(current)) && !in_interrupt())
>   alloc_flags |= ALLOC_HARDER;
>  
> - alloc_flags = current_alloc_flags(gfp_mask, alloc_flags);
> + alloc_flags = gpf_to_alloc_flags(gfp_mask, alloc_flags);
>  
>   return alloc_flags;
>  }
> @@ -4774,7 +4771,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int 
> order,
>  
>   reserve_flags = __gfp_pfmemalloc_flags(gfp_mask);
>   if (reserve_flags)
> - alloc_flags = current_alloc_flags(gfp_mask, reserve_flags);
> + alloc_flags = gpf_to_alloc_flags(gfp_mask, reserve_flags);
>  
>   /*
>* Reset the nodemask and zonelist iterators if memory policies can be
> @@ -4943,7 +4940,7 @@ static inline bool prepare_alloc_pages(gfp_t gfp_mask, 
> unsigned int order,
>   if (should_fail_alloc_page(gfp_mask, order))
>   return false;
>  
> - *alloc_flags = current_alloc_flags(gfp_mask, *alloc_flags);
> + *alloc_flags = gpf_to_alloc_flags(gfp_mask, *alloc_flags);

I have a question, what is the abbreviation of "gpf" in the function
name gpf_to_alloc_flags()?

It seems that this function still use gfp_mask, is this supposed
to be gfp (Get Free Page)?

Thanks,
Lecopzer



Re: [PATCH v2 4/4] arm64: kaslr: support randomized module area with KASAN_VMALLOC

2021-01-28 Thread Lecopzer Chen
 
> On Sat, Jan 09, 2021 at 06:32:52PM +0800, Lecopzer Chen wrote:
> > After KASAN_VMALLOC works in arm64, we can randomize module region
> > into vmalloc area now.
> > 
> > Test:
> > VMALLOC area ffc01000 fffdf000
> > 
> > before the patch:
> > module_alloc_base/end ffc008b8 ffc01000
> > after the patch:
> > module_alloc_base/end ffdcf4bed000 ffc01000
> > 
> > And the function that insmod some modules is fine.
> > 
> > Suggested-by: Ard Biesheuvel 
> > Signed-off-by: Lecopzer Chen 
> > ---
> >  arch/arm64/kernel/kaslr.c  | 18 ++
> >  arch/arm64/kernel/module.c | 16 +---
> >  2 files changed, 19 insertions(+), 15 deletions(-)
> > 
> > diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
> > index 1c74c45b9494..a2858058e724 100644
> > --- a/arch/arm64/kernel/kaslr.c
> > +++ b/arch/arm64/kernel/kaslr.c
> > @@ -161,15 +161,17 @@ u64 __init kaslr_early_init(u64 dt_phys)
> > /* use the top 16 bits to randomize the linear region */
> > memstart_offset_seed = seed >> 48;
> >  
> > -   if (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
> > -   IS_ENABLED(CONFIG_KASAN_SW_TAGS))
> > +   if (!IS_ENABLED(CONFIG_KASAN_VMALLOC) &&
> > +   (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
> 
> CONFIG_KASAN_VMALLOC depends on CONFIG_KASAN_GENERIC so why is this
> necessary?
> 
> Will

CONFIG_KASAN_VMALLOC=y means CONFIG_KASAN_GENERIC=y
but CONFIG_KASAN_GENERIC=y doesn't means CONFIG_KASAN_VMALLOC=y

So this if-condition allows only KASAN rather than
KASAN + KASAN_VMALLOC enabled.

Please correct me if I'm wrong.

thanks,
Lecopzer


 




Re: [PATCH] ARM: mm: harden branch predictor before opening interrupts during fault

2021-01-26 Thread Lecopzer Chen
Hi all,

I don't see any fix for this issue now(maybe I missed it..?),
could we fix this if there is better solution?
This issue exists almost two years.

Thanks!

BRs,
Lecopzer


Re: [PATCH] ARM: mm: harden branch predictor before opening interrupts during fault

2021-01-26 Thread Lecopzer Chen
> On Tue, Jan 26, 2021 at 11:01:50PM +0800, Lecopzer Chen wrote:
> > > On 2021-01-26 10:59:32 [+], Russell King - ARM Linux admin wrote:
> > > > On Tue, Jan 26, 2021 at 05:17:08PM +0800, Lecopzer Chen wrote:
> > > > > Hi all,
> > > > > 
> > > > > I don't see any fix for this issue now(maybe I missed it..?),
> > > > > could we fix this if there is better solution?
> > > > > This issue exists almost two years.
> > > > 
> > > > I don't think anyone provided an acceptable patch.
> > > > 
> > > > The first patch moved the hardening out of the translation/section
> > > > fault handling. Since the kernel is mapped with sections, these
> > > > are above TASK_SIZE, and the whole point of the branch prediction
> > > > hardening is to prevent the prediction in the kernel being exploited,
> > > > missing the hardening effectively makes the mitigation useless.
> > > > 
> > > > The discussion in February 2019 never concluded from what I can see.
> > > 
> > > My memory is that I never got a reply which I understood.
> > > Let me try again this week with the information above.
> > 
> > 
> > NOTE:
> > Before sending this mail, I had searched the relative threads and
> > there are two solutions in general:
> > 1. Add get_pcpu()/put_cpu() https://lkml.org/lkml/2019/6/3/426
> >Reject by Marc:
> >> The right fix would be to move the call to a point where we haven't
> >> enabled preemption yet.
> > 
> > 2. Move out like the patch from Sebastian:
> >This seems follow the concept of 1.
> >(move the call to a point where we haven't enabled preemption yet).
> >But I can't find any reply in the thread.
> > 
> > Now the CONFIG_HARDEN_BRANCH_PREDICTOR has already backported to LTS,
> > and after upgrading ARM CONFIG_CPU_V7 products to latest LTS, the
> > CONFIG_HARDEN_BRANCH_PREDICTOR will be default y and this issue makes
> > our devices panic and we have to either disable HARDEN_BRANCH_PREDICTOR
> > or hack in-house to avoid the kernel panic.
> 
> It does _not_ cause the kernel to panic, ever. A kernel panic takes
> out the system. This is not the case here.
> 
> It merely causes a noisy message to be emitted in the kernel log, and
> the system survives. That is way more preferable than breaking the
> effect of branch predictor hardening.
> 
> If it is taking out your kernel with a real panic, then there is
> something wrong elsewhere - and this is _not_ something that should
> be happening during normal system operation.

Oh, yes, you're right;

After reread the panic log, our panic happened because
-> invalid userspace memory access
-> debug_preempt log
-> the program seg fault
-> main service need the program but it crash
-> panic

Sorry for wrong information and thanks a lot for the correctness.
I think I have to see why the in-house hacking is working...

Thanks!!

BRs,
Lecopzer



Re: [PATCH] ARM: mm: harden branch predictor before opening interrupts during fault

2021-01-26 Thread Lecopzer Chen
> On 2021-01-26 10:59:32 [+], Russell King - ARM Linux admin wrote:
> > On Tue, Jan 26, 2021 at 05:17:08PM +0800, Lecopzer Chen wrote:
> > > Hi all,
> > > 
> > > I don't see any fix for this issue now(maybe I missed it..?),
> > > could we fix this if there is better solution?
> > > This issue exists almost two years.
> > 
> > I don't think anyone provided an acceptable patch.
> > 
> > The first patch moved the hardening out of the translation/section
> > fault handling. Since the kernel is mapped with sections, these
> > are above TASK_SIZE, and the whole point of the branch prediction
> > hardening is to prevent the prediction in the kernel being exploited,
> > missing the hardening effectively makes the mitigation useless.
> > 
> > The discussion in February 2019 never concluded from what I can see.
> 
> My memory is that I never got a reply which I understood.
> Let me try again this week with the information above.


NOTE:
Before sending this mail, I had searched the relative threads and
there are two solutions in general:
1. Add get_pcpu()/put_cpu() https://lkml.org/lkml/2019/6/3/426
   Reject by Marc:
   > The right fix would be to move the call to a point where we haven't
   > enabled preemption yet.

2. Move out like the patch from Sebastian:
   This seems follow the concept of 1.
   (move the call to a point where we haven't enabled preemption yet).
   But I can't find any reply in the thread.

Now the CONFIG_HARDEN_BRANCH_PREDICTOR has already backported to LTS,
and after upgrading ARM CONFIG_CPU_V7 products to latest LTS, the
CONFIG_HARDEN_BRANCH_PREDICTOR will be default y and this issue makes
our devices panic and we have to either disable HARDEN_BRANCH_PREDICTOR
or hack in-house to avoid the kernel panic.


I'll wait for anyone have acceptable idea and patching(maybe Sebastian could? 
:)),
and I'll also take some time to find other solution too.


Thanks,
Lecopzer



Re: [PATCH v2 0/4] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-01-21 Thread Lecopzer Chen
Dear reviewers and maintainers,


Could we have chance to upstream this in 5.12-rc?

So if these patches have any problem I can fix as soon as possible before
next -rc comming.


thanks!

BRs,
Lecopzer


[RESEND PATCH] kasan: fix incorrect arguments passing in kasan_add_zero_shadow

2021-01-13 Thread Lecopzer Chen
kasan_remove_zero_shadow() shall use original virtual address, start
and size, instead of shadow address.

Fixes: 0207df4fa1a86 ("kernel/memremap, kasan: make ZONE_DEVICE with work with 
KASAN")
Signed-off-by: Lecopzer Chen 
Reviewed-by: Andrey Konovalov 
Cc: Andrey Ryabinin 
Cc: Dan Williams 
Cc: Dmitry Vyukov 
Cc: Alexander Potapenko 
Signed-off-by: Andrew Morton 
---
 mm/kasan/init.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mm/kasan/init.c b/mm/kasan/init.c
index bc0ad208b3a7..67051cfae41c 100644
--- a/mm/kasan/init.c
+++ b/mm/kasan/init.c
@@ -481,7 +481,6 @@ int kasan_add_zero_shadow(void *start, unsigned long size)
 
ret = kasan_populate_early_shadow(shadow_start, shadow_end);
if (ret)
-   kasan_remove_zero_shadow(shadow_start,
-   size >> KASAN_SHADOW_SCALE_SHIFT);
+   kasan_remove_zero_shadow(start, size);
return ret;
 }
-- 
2.25.1


[PATCH v2 1/4] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-01-09 Thread Lecopzer Chen
Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Like how the MODULES_VADDR does now, just not to early populate
the VMALLOC_START between VMALLOC_END.
similarly, the kernel code mapping is now in the VMALLOC area and
should keep these area populated.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/mm/kasan_init.c | 23 ++-
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index d8e66c78440e..39b218a64279 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
 {
u64 kimg_shadow_start, kimg_shadow_end;
u64 mod_shadow_start, mod_shadow_end;
+   u64 vmalloc_shadow_start, vmalloc_shadow_end;
phys_addr_t pa_start, pa_end;
u64 i;
 
@@ -223,6 +224,9 @@ static void __init kasan_init_shadow(void)
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
 
+   vmalloc_shadow_start = (u64)kasan_mem_to_shadow((void *)VMALLOC_START);
+   vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END);
+
/*
 * We are going to perform proper setup of shadow memory.
 * At first we should unmap early shadow (clear_pgds() call below).
@@ -241,12 +245,21 @@ static void __init kasan_init_shadow(void)
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-   kasan_populate_early_shadow((void *)kimg_shadow_end,
-  (void *)KASAN_SHADOW_END);
+   if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
+   kasan_populate_early_shadow((void *)vmalloc_shadow_end,
+   (void *)KASAN_SHADOW_END);
+   if (vmalloc_shadow_start > mod_shadow_end)
+   kasan_populate_early_shadow((void *)mod_shadow_end,
+   (void 
*)vmalloc_shadow_start);
+
+   } else {
+   kasan_populate_early_shadow((void *)kimg_shadow_end,
+   (void *)KASAN_SHADOW_END);
+   if (kimg_shadow_start > mod_shadow_end)
+   kasan_populate_early_shadow((void *)mod_shadow_end,
+   (void *)kimg_shadow_start);
+   }
 
-   if (kimg_shadow_start > mod_shadow_end)
-   kasan_populate_early_shadow((void *)mod_shadow_end,
-   (void *)kimg_shadow_start);
 
for_each_mem_range(i, _start, _end) {
void *start = (void *)__phys_to_virt(pa_start);
-- 
2.25.1



[PATCH v2 4/4] arm64: kaslr: support randomized module area with KASAN_VMALLOC

2021-01-09 Thread Lecopzer Chen
After KASAN_VMALLOC works in arm64, we can randomize module region
into vmalloc area now.

Test:
VMALLOC area ffc01000 fffdf000

before the patch:
module_alloc_base/end ffc008b8 ffc01000
after the patch:
module_alloc_base/end ffdcf4bed000 ffc01000

And the function that insmod some modules is fine.

Suggested-by: Ard Biesheuvel 
Signed-off-by: Lecopzer Chen 
---
 arch/arm64/kernel/kaslr.c  | 18 ++
 arch/arm64/kernel/module.c | 16 +---
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
index 1c74c45b9494..a2858058e724 100644
--- a/arch/arm64/kernel/kaslr.c
+++ b/arch/arm64/kernel/kaslr.c
@@ -161,15 +161,17 @@ u64 __init kaslr_early_init(u64 dt_phys)
/* use the top 16 bits to randomize the linear region */
memstart_offset_seed = seed >> 48;
 
-   if (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
-   IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+   if (!IS_ENABLED(CONFIG_KASAN_VMALLOC) &&
+   (IS_ENABLED(CONFIG_KASAN_GENERIC) ||
+IS_ENABLED(CONFIG_KASAN_SW_TAGS)))
/*
-* KASAN does not expect the module region to intersect the
-* vmalloc region, since shadow memory is allocated for each
-* module at load time, whereas the vmalloc region is shadowed
-* by KASAN zero pages. So keep modules out of the vmalloc
-* region if KASAN is enabled, and put the kernel well within
-* 4 GB of the module region.
+* KASAN without KASAN_VMALLOC does not expect the module region
+* to intersect the vmalloc region, since shadow memory is
+* allocated for each module at load time, whereas the vmalloc
+* region is shadowed by KASAN zero pages. So keep modules
+* out of the vmalloc region if KASAN is enabled without
+* KASAN_VMALLOC, and put the kernel well within 4 GB of the
+* module region.
 */
return offset % SZ_2G;
 
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index fe21e0f06492..b5ec010c481f 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -40,14 +40,16 @@ void *module_alloc(unsigned long size)
NUMA_NO_NODE, __builtin_return_address(0));
 
if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
-   !IS_ENABLED(CONFIG_KASAN_GENERIC) &&
-   !IS_ENABLED(CONFIG_KASAN_SW_TAGS))
+   (IS_ENABLED(CONFIG_KASAN_VMALLOC) ||
+(!IS_ENABLED(CONFIG_KASAN_GENERIC) &&
+ !IS_ENABLED(CONFIG_KASAN_SW_TAGS
/*
-* KASAN can only deal with module allocations being served
-* from the reserved module region, since the remainder of
-* the vmalloc region is already backed by zero shadow pages,
-* and punching holes into it is non-trivial. Since the module
-* region is not randomized when KASAN is enabled, it is even
+* KASAN without KASAN_VMALLOC can only deal with module
+* allocations being served from the reserved module region,
+* since the remainder of the vmalloc region is already
+* backed by zero shadow pages, and punching holes into it
+* is non-trivial. Since the module region is not randomized
+* when KASAN is enabled without KASAN_VMALLOC, it is even
 * less likely that the module region gets exhausted, so we
 * can simply omit this fallback in that case.
 */
-- 
2.25.1



[PATCH v2 2/4] arm64: kasan: abstract _text and _end to KERNEL_START/END

2021-01-09 Thread Lecopzer Chen
Arm64 provide defined macro for KERNEL_START and KERNEL_END,
thus replace them by the abstration instead of using _text and _end.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/mm/kasan_init.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index 39b218a64279..fa8d7ece895d 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -218,8 +218,8 @@ static void __init kasan_init_shadow(void)
phys_addr_t pa_start, pa_end;
u64 i;
 
-   kimg_shadow_start = (u64)kasan_mem_to_shadow(_text) & PAGE_MASK;
-   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(_end));
+   kimg_shadow_start = (u64)kasan_mem_to_shadow(KERNEL_START) & PAGE_MASK;
+   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(KERNEL_END));
 
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
@@ -241,7 +241,7 @@ static void __init kasan_init_shadow(void)
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
 
kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
-  early_pfn_to_nid(virt_to_pfn(lm_alias(_text;
+  
early_pfn_to_nid(virt_to_pfn(lm_alias(KERNEL_START;
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-- 
2.25.1



[PATCH v2 0/4] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-01-09 Thread Lecopzer Chen
Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Acroding to how x86 ported it [1], they early allocated p4d and pgd,
but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
by not to populate the vmalloc area except for kimg address.

Test environment:
4G and 8G Qemu virt, 
39-bit VA + 4k PAGE_SIZE with 3-level page table,
test by lib/test_kasan.ko and lib/test_kasan_module.ko

It also works in Kaslr with CONFIG_RANDOMIZE_MODULE_REGION_FULL
and randomize module region inside vmalloc area.


[1]: commit 0609ae011deb41c ("x86/kasan: support KASAN_VMALLOC")

Signed-off-by: Lecopzer Chen 
Acked-by: Andrey Konovalov 
Tested-by: Andrey Konovalov 


v2 -> v1
1. kasan_init.c tweak indent
2. change Kconfig depends only on HAVE_ARCH_KASAN
3. support randomized module region.

v1:
https://lore.kernel.org/lkml/20210103171137.153834-1-lecop...@gmail.com/

Lecopzer Chen (4):
  arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC
  arm64: kasan: abstract _text and _end to KERNEL_START/END
  arm64: Kconfig: support CONFIG_KASAN_VMALLOC
  arm64: kaslr: support randomized module area with KASAN_VMALLOC

 arch/arm64/Kconfig |  1 +
 arch/arm64/kernel/kaslr.c  | 18 ++
 arch/arm64/kernel/module.c | 16 +---
 arch/arm64/mm/kasan_init.c | 29 +
 4 files changed, 41 insertions(+), 23 deletions(-)

-- 
2.25.1



[PATCH v2 3/4] arm64: Kconfig: support CONFIG_KASAN_VMALLOC

2021-01-09 Thread Lecopzer Chen
now we can backed shadow memory in vmalloc area,
thus support KASAN_VMALLOC in KASAN_GENERIC mode.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 05e17351e4f3..ba03820402ee 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -136,6 +136,7 @@ config ARM64
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
+   select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_HW_TAGS if (HAVE_ARCH_KASAN && ARM64_MTE)
select HAVE_ARCH_KGDB
-- 
2.25.1



Re: [PATCH 0/3] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-01-09 Thread Lecopzer Chen
Hi Ard,

> On Fri, 8 Jan 2021 at 19:31, Andrey Konovalov  wrote:
> >
> > On Sun, Jan 3, 2021 at 6:12 PM Lecopzer Chen  wrote:
> > >
> > > Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > > ("kasan: support backing vmalloc space with real shadow memory")
> > >
> > > Acroding to how x86 ported it [1], they early allocated p4d and pgd,
> > > but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
> > > by not to populate the vmalloc area except for kimg address.
> > >
> > > Test environment:
> > > 4G and 8G Qemu virt,
> > > 39-bit VA + 4k PAGE_SIZE with 3-level page table,
> > > test by lib/test_kasan.ko and lib/test_kasan_module.ko
> > >
> > > It also works in Kaslr with CONFIG_RANDOMIZE_MODULE_REGION_FULL,
> > > but not test for HW_TAG(I have no proper device), thus keep
> > > HW_TAG and KASAN_VMALLOC mutual exclusion until confirming
> > > the functionality.
> > >
> > >
> > > [1]: commit 0609ae011deb41c ("x86/kasan: support KASAN_VMALLOC")
> > >
> > > Signed-off-by: Lecopzer Chen 
> >
> > Hi Lecopzer,
> >
> > Thanks for working on this!
> >
> > Acked-by: Andrey Konovalov 
> > Tested-by: Andrey Konovalov 
> >
> > for the series along with the other two patches minding the nit in patch #3.
> >
> > Will, Catalin, could you please take a look at the arm changes?
> >
> > Thanks!
> >
> 
> 
> If vmalloc can now be backed with real shadow memory, we no longer
> have to keep the module region in its default location when KASLR and
> KASAN are both enabled.
> 
> So the check on line 164 in arch/arm64/kernel/kaslr.c should probably
> be updated to reflect this change.
> 

I've tested supporting module region randomized and It looks fine
in some easy test(insmod some modules).

I'll add this to patch v2, thanks for your suggestion.

BRs,
Lecopzer


Re: [PATCH 0/3] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-01-08 Thread Lecopzer Chen
Hi Andrey,
>  
> On Sun, Jan 3, 2021 at 6:12 PM Lecopzer Chen  wrote:
> >
> > Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
> > ("kasan: support backing vmalloc space with real shadow memory")
> >
> > Acroding to how x86 ported it [1], they early allocated p4d and pgd,
> > but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
> > by not to populate the vmalloc area except for kimg address.
> >
> > Test environment:
> > 4G and 8G Qemu virt,
> > 39-bit VA + 4k PAGE_SIZE with 3-level page table,
> > test by lib/test_kasan.ko and lib/test_kasan_module.ko
> >
> > It also works in Kaslr with CONFIG_RANDOMIZE_MODULE_REGION_FULL,
> > but not test for HW_TAG(I have no proper device), thus keep
> > HW_TAG and KASAN_VMALLOC mutual exclusion until confirming
> > the functionality.
> 
> Re this: it makes sense to introduce vmalloc support one step a time
> and add SW_TAGS support before taking on HW_TAGS. SW_TAGS doesn't
> require any special hardware. Working on SW_TAGS first will also allow
> dealing with potential conflicts between vmalloc and tags without
> having MTE in the picture as well. Just FYI, no need to include that
> in this change.

Thanks for the information and suggestion, so this serise I'll keep 
only for KASAN_GENERIC support :)



BRs,
Lecopzer



Re: [PATCH 3/3] arm64: Kconfig: support CONFIG_KASAN_VMALLOC

2021-01-08 Thread Lecopzer Chen
Hi Andrey,
 
> On Sun, Jan 3, 2021 at 6:13 PM Lecopzer Chen  wrote:
> >
> > Now I have no device to test for HW_TAG, so keep it not selected
> > until someone can test this.
> >
> > Signed-off-by: Lecopzer Chen 
> > ---
> >  arch/arm64/Kconfig | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > index 05e17351e4f3..29ab35aab59e 100644
> > --- a/arch/arm64/Kconfig
> > +++ b/arch/arm64/Kconfig
> > @@ -136,6 +136,7 @@ config ARM64
> > select HAVE_ARCH_JUMP_LABEL
> > select HAVE_ARCH_JUMP_LABEL_RELATIVE
> > select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
> > +   select HAVE_ARCH_KASAN_VMALLOC if (HAVE_ARCH_KASAN && 
> > !KASAN_HW_TAGS)
> 
> KASAN_VMALLOC currently "depends on" KASAN_GENERIC. I think we should
> either do "HAVE_ARCH_KASAN && KASAN_GENERIC" here as well, or just do
> "if HAVE_ARCH_KASAN".

Thanks for the correctness, I'll change to the following in V2 patch.
"select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN"

Let KASAN_VMALLOC depend on the mode it supports to avoid modifying
two places if KASAN_VMALLOC can support other than GENERIC in the future.


Re: [PATCH v2] arm64: perf: Fix access percpu variables in preemptible context

2021-01-08 Thread Lecopzer Chen
Hi Sumit,
 
Thanks for your reply.
 
> On Mon, 21 Dec 2020 at 21:53, Lecopzer Chen  
> wrote:
> >
> > commit 367c820ef08082 ("arm64: Enable perf events based hard lockup 
> > detector")
> > reinitilizes lockup detector after arm64 PMU is initialized and open
> > a window for accessing smp_processor_id() in preemptible context.
> > Since hardlockup_detector_perf_init() always called in init stage
> > with a single cpu, but we initialize lockup detector after the init task
> > is migratable.
> >
> > Fix this by utilizing lockup detector reconfiguration which calls
> > softlockup_start_all() on each cpu and calls watatchdog_nmi_enable() later.
> > Because softlockup_start_all() use IPI call function to make sure
> > watatchdog_nmi_enable() will bind on each cpu and fix this issue.
> 
> IMO, this just creates unnecessary dependency for hardlockup detector
> init via softlockup detector (see the alternative definition of
> lockup_detector_reconfigure()).


The arm64/Kconfig select HAVE_HARDLOCKUP_DETECTOR_PERF if we have NMI:
select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && 
HAVE_PERF_EVENTS_NMI

And in lib/Kconfig.debug HARDLOCKUP_DETECTOR select SOFTLOCKUP_DETECTOR 
automatically.
config HARDLOCKUP_DETECTOR_PERF
bool
select SOFTLOCKUP_DETECTOR

So we don't need to explicitly select softlockup.
And actually this patch is not a perfect solution like you said
(hardlockup depends on softlockup),
but the key point is that lockup_detector_init() seems only design for
using in early init stage and not for calling in later deffered initial process.


> 
> >
> > BUG: using smp_processor_id() in preemptible [] code: 
> > swapper/0/1
> 
> How about just the below fix in order to make CONFIG_DEBUG_PREEMPT happy?
> 
> diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c
> index 247bf0b1582c..db06ee28f48e 100644
> --- a/kernel/watchdog_hld.c
> +++ b/kernel/watchdog_hld.c
> @@ -165,7 +165,7 @@ static void watchdog_overflow_callback(struct
> perf_event *event,
> 
>  static int hardlockup_detector_event_create(void)
>  {
> -   unsigned int cpu = smp_processor_id();
> +   unsigned int cpu = raw_smp_processor_id();
> struct perf_event_attr *wd_attr;
> struct perf_event *evt;
> 

This won't solve the issue that arm64 called this in preemptible context,
I was trying to find a balance that can pass CONFIG_DEBUG_PREEMPT and
calling lockup_detector_init() in non-preemptive context.

watchdog_nmi_probe() and the following hardlockup_detector_event_create use
this_cpu_read/write, thus the topic of solution is better to be
'how to call lockup_detector_init() in preemptive context'

we can't just use preempt_disable/enable between lockup_detector_init() because
the call tree inside it will use kamlloc() with GFP_KERNEL which would check by 
might_sleep()


The v2 is now what I can find to solve this and the smallest change.
But the drawback, again, is hardlockup depends on softlockup.

The other solution may be executed lockup_detector_init in a binded thread
which only bind to one cpu.


BRs,
Lecopzer


> -Sumit
> 
> > caller is debug_smp_processor_id+0x20/0x2c
> > CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.10.0+ #276
> > Hardware name: linux,dummy-virt (DT)
> > Call trace:
> >   dump_backtrace+0x0/0x3c0
> >   show_stack+0x20/0x6c
> >   dump_stack+0x2f0/0x42c
> >   check_preemption_disabled+0x1cc/0x1dc
> >   debug_smp_processor_id+0x20/0x2c
> >   hardlockup_detector_event_create+0x34/0x18c
> >   hardlockup_detector_perf_init+0x2c/0x134
> >   watchdog_nmi_probe+0x18/0x24
> >   lockup_detector_init+0x44/0xa8
> >   armv8_pmu_driver_init+0x54/0x78
> >   do_one_initcall+0x184/0x43c
> >   kernel_init_freeable+0x368/0x380
> >   kernel_init+0x1c/0x1cc
> >   ret_from_fork+0x10/0x30
> 


[PATCH 3/3] arm64: Kconfig: support CONFIG_KASAN_VMALLOC

2021-01-03 Thread Lecopzer Chen
Now I have no device to test for HW_TAG, so keep it not selected
until someone can test this.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 05e17351e4f3..29ab35aab59e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -136,6 +136,7 @@ config ARM64
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
+   select HAVE_ARCH_KASAN_VMALLOC if (HAVE_ARCH_KASAN && !KASAN_HW_TAGS)
select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN
select HAVE_ARCH_KASAN_HW_TAGS if (HAVE_ARCH_KASAN && ARM64_MTE)
select HAVE_ARCH_KGDB
-- 
2.25.1



[PATCH 2/3] arm64: kasan: abstract _text and _end to KERNEL_START/END

2021-01-03 Thread Lecopzer Chen
Arm64 provide defined macro for KERNEL_START and KERNEL_END,
thus replace by the abstration instead of using _text and _end directly.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/mm/kasan_init.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index d7ad3f1e9c4d..acb549951f87 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -218,8 +218,8 @@ static void __init kasan_init_shadow(void)
phys_addr_t pa_start, pa_end;
u64 i;
 
-   kimg_shadow_start = (u64)kasan_mem_to_shadow(_text) & PAGE_MASK;
-   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(_end));
+   kimg_shadow_start = (u64)kasan_mem_to_shadow(KERNEL_START) & PAGE_MASK;
+   kimg_shadow_end = PAGE_ALIGN((u64)kasan_mem_to_shadow(KERNEL_END));
 
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
@@ -241,7 +241,7 @@ static void __init kasan_init_shadow(void)
clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
 
kasan_map_populate(kimg_shadow_start, kimg_shadow_end,
-  early_pfn_to_nid(virt_to_pfn(lm_alias(_text;
+  
early_pfn_to_nid(virt_to_pfn(lm_alias(KERNEL_START;
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-- 
2.25.1



[PATCH 1/3] arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC

2021-01-03 Thread Lecopzer Chen
Linux support KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Like how the MODULES_VADDR does now, just not to early populate
the VMALLOC_START between VMALLOC_END.
similarly, the kernel code mapping is now in the VMALLOC area and
should keep these area populated.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/mm/kasan_init.c | 23 ++-
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index d8e66c78440e..d7ad3f1e9c4d 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -214,6 +214,7 @@ static void __init kasan_init_shadow(void)
 {
u64 kimg_shadow_start, kimg_shadow_end;
u64 mod_shadow_start, mod_shadow_end;
+   u64 vmalloc_shadow_start, vmalloc_shadow_end;
phys_addr_t pa_start, pa_end;
u64 i;
 
@@ -223,6 +224,9 @@ static void __init kasan_init_shadow(void)
mod_shadow_start = (u64)kasan_mem_to_shadow((void *)MODULES_VADDR);
mod_shadow_end = (u64)kasan_mem_to_shadow((void *)MODULES_END);
 
+   vmalloc_shadow_start = (u64)kasan_mem_to_shadow((void *)VMALLOC_START);
+   vmalloc_shadow_end = (u64)kasan_mem_to_shadow((void *)VMALLOC_END);
+
/*
 * We are going to perform proper setup of shadow memory.
 * At first we should unmap early shadow (clear_pgds() call below).
@@ -241,12 +245,21 @@ static void __init kasan_init_shadow(void)
 
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END),
   (void *)mod_shadow_start);
-   kasan_populate_early_shadow((void *)kimg_shadow_end,
-  (void *)KASAN_SHADOW_END);
+   if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
+   kasan_populate_early_shadow((void *)vmalloc_shadow_end,
+  (void *)KASAN_SHADOW_END);
+   if (vmalloc_shadow_start > mod_shadow_end)
+   kasan_populate_early_shadow((void *)mod_shadow_end,
+   (void 
*)vmalloc_shadow_start);
+
+   }   else {
+   kasan_populate_early_shadow((void *)kimg_shadow_end,
+  (void *)KASAN_SHADOW_END);
+   if (kimg_shadow_start > mod_shadow_end)
+   kasan_populate_early_shadow((void *)mod_shadow_end,
+   (void *)kimg_shadow_start);
+   }
 
-   if (kimg_shadow_start > mod_shadow_end)
-   kasan_populate_early_shadow((void *)mod_shadow_end,
-   (void *)kimg_shadow_start);
 
for_each_mem_range(i, _start, _end) {
void *start = (void *)__phys_to_virt(pa_start);
-- 
2.25.1



[PATCH 0/3] arm64: kasan: support CONFIG_KASAN_VMALLOC

2021-01-03 Thread Lecopzer Chen
Linux supports KAsan for VMALLOC since commit 3c5c3cfb9ef4da9
("kasan: support backing vmalloc space with real shadow memory")

Acroding to how x86 ported it [1], they early allocated p4d and pgd,
but in arm64 I just simulate how KAsan supports MODULES_VADDR in arm64
by not to populate the vmalloc area except for kimg address.

Test environment:
4G and 8G Qemu virt, 
39-bit VA + 4k PAGE_SIZE with 3-level page table,
test by lib/test_kasan.ko and lib/test_kasan_module.ko

It also works in Kaslr with CONFIG_RANDOMIZE_MODULE_REGION_FULL,
but not test for HW_TAG(I have no proper device), thus keep
HW_TAG and KASAN_VMALLOC mutual exclusion until confirming
the functionality.


[1]: commit 0609ae011deb41c ("x86/kasan: support KASAN_VMALLOC")

Signed-off-by: Lecopzer Chen 


Lecopzer Chen (3):
  arm64: kasan: don't populate vmalloc area for CONFIG_KASAN_VMALLOC
  arm64: kasan: abstract _text and _end to KERNEL_START/END
  arm64: Kconfig: support CONFIG_KASAN_VMALLOC

 arch/arm64/Kconfig |  1 +
 arch/arm64/mm/kasan_init.c | 29 +
 2 files changed, 22 insertions(+), 8 deletions(-)

-- 
2.25.1



[PATCH] kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow

2021-01-03 Thread Lecopzer Chen
During testing kasan_populate_early_shadow and kasan_remove_zero_shadow,
if the shadow start and end address in kasan_remove_zero_shadow() is
not aligned to PMD_SIZE, the remain unaligned PTE won't be removed.

In the test case for kasan_remove_zero_shadow():
shadow_start: 0xffb80200, shadow end: 0xffbfbe00
3-level page table:
  PUD_SIZE: 0x4000 PMD_SIZE: 0x20 PAGE_SIZE: 4K
0xffbf8000 ~ 0xffbfbdf8 will not be removed because
in kasan_remove_pud_table(), kasan_pmd_table(*pud) is true but the
next address is 0xffbfbdf8 which is not aligned to PUD_SIZE.

In the correct condition, this should fallback to the next level
kasan_remove_pmd_table() but the condition flow always continue to skip
the unaligned part.

Fix by correcting the condition when next and addr are neither aligned.

Fixes: 0207df4fa1a86 ("kernel/memremap, kasan: make ZONE_DEVICE with work with 
KASAN")
Signed-off-by: Lecopzer Chen 
---
 mm/kasan/init.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/mm/kasan/init.c b/mm/kasan/init.c
index 67051cfae41c..ae9158f7501f 100644
--- a/mm/kasan/init.c
+++ b/mm/kasan/init.c
@@ -372,9 +372,10 @@ static void kasan_remove_pmd_table(pmd_t *pmd, unsigned 
long addr,
 
if (kasan_pte_table(*pmd)) {
if (IS_ALIGNED(addr, PMD_SIZE) &&
-   IS_ALIGNED(next, PMD_SIZE))
+   IS_ALIGNED(next, PMD_SIZE)) {
pmd_clear(pmd);
-   continue;
+   continue;
+   }
}
pte = pte_offset_kernel(pmd, addr);
kasan_remove_pte_table(pte, addr, next);
@@ -397,9 +398,10 @@ static void kasan_remove_pud_table(pud_t *pud, unsigned 
long addr,
 
if (kasan_pmd_table(*pud)) {
if (IS_ALIGNED(addr, PUD_SIZE) &&
-   IS_ALIGNED(next, PUD_SIZE))
+   IS_ALIGNED(next, PUD_SIZE)) {
pud_clear(pud);
-   continue;
+   continue;
+   }
}
pmd = pmd_offset(pud, addr);
pmd_base = pmd_offset(pud, 0);
@@ -423,9 +425,10 @@ static void kasan_remove_p4d_table(p4d_t *p4d, unsigned 
long addr,
 
if (kasan_pud_table(*p4d)) {
if (IS_ALIGNED(addr, P4D_SIZE) &&
-   IS_ALIGNED(next, P4D_SIZE))
+   IS_ALIGNED(next, P4D_SIZE)) {
p4d_clear(p4d);
-   continue;
+   continue;
+   }
}
pud = pud_offset(p4d, addr);
kasan_remove_pud_table(pud, addr, next);
@@ -456,9 +459,10 @@ void kasan_remove_zero_shadow(void *start, unsigned long 
size)
 
if (kasan_p4d_table(*pgd)) {
if (IS_ALIGNED(addr, PGDIR_SIZE) &&
-   IS_ALIGNED(next, PGDIR_SIZE))
+   IS_ALIGNED(next, PGDIR_SIZE)) {
pgd_clear(pgd);
-   continue;
+   continue;
+   }
}
 
p4d = p4d_offset(pgd, addr);
-- 
2.25.1



[PATCH] kasan: fix incorrect arguments passing in kasan_add_zero_shadow

2021-01-02 Thread Lecopzer Chen
kasan_remove_zero_shadow() shall use original virtual address, start
and size, instead of shadow address.

Fixes: 0207df4fa1a86 ("kernel/memremap, kasan: make ZONE_DEVICE with work with 
KASAN")
Signed-off-by: Lecopzer Chen 
---
 mm/kasan/init.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mm/kasan/init.c b/mm/kasan/init.c
index bc0ad208b3a7..67051cfae41c 100644
--- a/mm/kasan/init.c
+++ b/mm/kasan/init.c
@@ -481,7 +481,6 @@ int kasan_add_zero_shadow(void *start, unsigned long size)
 
ret = kasan_populate_early_shadow(shadow_start, shadow_end);
if (ret)
-   kasan_remove_zero_shadow(shadow_start,
-   size >> KASAN_SHADOW_SCALE_SHIFT);
+   kasan_remove_zero_shadow(start, size);
return ret;
 }
-- 
2.25.1



[PATCH v2] arm64: perf: Fix access percpu variables in preemptible context

2020-12-21 Thread Lecopzer Chen
commit 367c820ef08082 ("arm64: Enable perf events based hard lockup detector")
reinitilizes lockup detector after arm64 PMU is initialized and open
a window for accessing smp_processor_id() in preemptible context.
Since hardlockup_detector_perf_init() always called in init stage
with a single cpu, but we initialize lockup detector after the init task
is migratable.

Fix this by utilizing lockup detector reconfiguration which calls
softlockup_start_all() on each cpu and calls watatchdog_nmi_enable() later.
Because softlockup_start_all() use IPI call function to make sure
watatchdog_nmi_enable() will bind on each cpu and fix this issue.

BUG: using smp_processor_id() in preemptible [] code: swapper/0/1
caller is debug_smp_processor_id+0x20/0x2c
CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.10.0+ #276
Hardware name: linux,dummy-virt (DT)
Call trace:
  dump_backtrace+0x0/0x3c0
  show_stack+0x20/0x6c
  dump_stack+0x2f0/0x42c
  check_preemption_disabled+0x1cc/0x1dc
  debug_smp_processor_id+0x20/0x2c
  hardlockup_detector_event_create+0x34/0x18c
  hardlockup_detector_perf_init+0x2c/0x134
  watchdog_nmi_probe+0x18/0x24
  lockup_detector_init+0x44/0xa8
  armv8_pmu_driver_init+0x54/0x78
  do_one_initcall+0x184/0x43c
  kernel_init_freeable+0x368/0x380
  kernel_init+0x1c/0x1cc
  ret_from_fork+0x10/0x30


Fixes: 367c820ef08082 ("arm64: Enable perf events based hard lockup detector")
Signed-off-by: Lecopzer Chen 
Reported-by: kernel test robot 
Cc: Sumit Garg 
---

Changelog v1 -> v2:
* 
https://lore.kernel.org/lkml/20201217130617.32202-1-lecopzer.c...@mediatek.com/
* Move solution from kernel/watchdog_hld.c to arm64 perf_event
* avoid preemptive kmalloc in preempt_disable().



 arch/arm64/kernel/perf_event.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 38bb07eff872..c03e21210bbb 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -1345,4 +1345,20 @@ u64 hw_nmi_get_sample_period(int watchdog_thresh)
 
return (u64)max_cpu_freq * watchdog_thresh;
 }
+
+/*
+ * hardlockup_detector_perf_init() always call in init stage with a single
+ * cpu. In arm64 case, we re-initialize lockup detector after pmu driver
+ * initialized. Lockup detector initial function use lots of percpu variables
+ * and this makes CONFIG_DEBUG_PREEMPT unhappy because we are now in
+ * preemptive context.
+ * Return 0 if the nmi is ready and register nmi hardlockup detector by
+ * lockup detector reconfiguration.
+ */
+int __init watchdog_nmi_probe(void)
+{
+   if (arm_pmu_irq_is_nmi())
+   return 0;
+   return -ENODEV;
+}
 #endif
-- 
2.25.1



Re: [PATCH] kernel/watchdog_hld.c: Fix access percpu in preemptible context

2020-12-19 Thread Lecopzer Chen


Thanks a lot, I'll try to fix this in anthoer way(patch v2) to avoid
regreesion other than arm64

BRs,
Lecopzer


> Greeting,
> 
> FYI, we noticed the following commit (built with gcc-9):
> 
> commit: 6e37d53a67753bcb12a0b9102cac85d98f8a0453 ("[PATCH] 
> kernel/watchdog_hld.c: Fix access percpu in preemptible context")
> url: 
> https://github.com/0day-ci/linux/commits/Lecopzer-Chen/kernel-watchdog_hld-c-Fix-access-percpu-in-preemptible-context/20201217-211549
> base: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git 
> accefff5b547a9a1d959c7e76ad539bf2480e78b
> 
> in testcase: boot
> 
> on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 8G
> 
> caused below changes (please refer to attached dmesg/kmsg for entire 
> log/backtrace):
> 
> If you fix the issue, kindly add following tag
> Reported-by: kernel test robot 
> 


Re: [PATCH] kernel/watchdog_hld.c: Fix access percpu in preemptible context

2020-12-19 Thread Lecopzer Chen
BRs,
Lecopzer


> Greeting,
> 
> FYI, we noticed the following commit (built with gcc-9):
> 
> commit: 6e37d53a67753bcb12a0b9102cac85d98f8a0453 ("[PATCH] 
> kernel/watchdog_hld.c: Fix access percpu in preemptible context")
> url: 
> https://github.com/0day-ci/linux/commits/Lecopzer-Chen/kernel-watchdog_hld-c-Fix-access-percpu-in-preemptible-context/20201217-211549
> base: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git 
> accefff5b547a9a1d959c7e76ad539bf2480e78b
> 
> in testcase: boot
> 
> on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 8G
> 
> caused below changes (please refer to attached dmesg/kmsg for entire 
> log/backtrace):
> 
> If you fix the issue, kindly add following tag
> Reported-by: kernel test robot 
> 


Re: [PATCH] arm64: Kconfig: Add SYS_SUPPORTS_APM_EMULATION

2020-12-17 Thread Lecopzer Chen
Hi Catalin,
 
Thanks for your explanation.
 
> > so there is two points
> > 1. out-of-tree function can't be approved
> > I totally agree with this :) so we may have a driver upstream in the 
> > future.
> 
> It may not be upstreamable if it relies on the old APM interface ;).
> 
> > 2. APM not make sense on arm64
> > Could you please let me konw the reason why APM on ARM64 doesn't make sense?
> 
> It's a very old interface, even on x86 it is disabled in the distro
> kernels. There are more modern alternatives and you should update your
> driver and user space to use them (e.g. /sys/power/).

Got it! I will disscuss with our internal team to update their drivers.

thanks a lot!

BRs,
Lecopzer


[PATCH] kernel/watchdog_hld.c: Fix access percpu in preemptible context

2020-12-17 Thread Lecopzer Chen
commit 367c820ef08082 ("arm64: Enable perf events based hard lockup detector")
reinitilizes lockup detector after arm64 PMU is initialized and provide
another chance for access smp_processor_id() in preemptible context.
Since hardlockup_detector_event_create() use many percpu relative variable,
just try to fix this by get/put_cpu()

BUG: using smp_processor_id() in preemptible [] code: swapper/0/1
caller is debug_smp_processor_id+0x20/0x2c
CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.10.0+ #276
Hardware name: linux,dummy-virt (DT)
Call trace:
  dump_backtrace+0x0/0x3c0
  show_stack+0x20/0x6c
  dump_stack+0x2f0/0x42c
  check_preemption_disabled+0x1cc/0x1dc
  debug_smp_processor_id+0x20/0x2c
  hardlockup_detector_event_create+0x34/0x18c
  hardlockup_detector_perf_init+0x2c/0x134
  watchdog_nmi_probe+0x18/0x24
  lockup_detector_init+0x44/0xa8
  armv8_pmu_driver_init+0x54/0x78
  do_one_initcall+0x184/0x43c
  kernel_init_freeable+0x368/0x380
  kernel_init+0x1c/0x1cc
  ret_from_fork+0x10/0x30


Fixes: 367c820ef08082 ("arm64: Enable perf events based hard lockup detector")
Signed-off-by: Lecopzer Chen 
Cc: Sumit Garg 

---
 kernel/watchdog_hld.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c
index 247bf0b1582c..c591a1ea8eb3 100644
--- a/kernel/watchdog_hld.c
+++ b/kernel/watchdog_hld.c
@@ -165,7 +165,7 @@ static void watchdog_overflow_callback(struct perf_event 
*event,
 
 static int hardlockup_detector_event_create(void)
 {
-   unsigned int cpu = smp_processor_id();
+   unsigned int cpu = get_cpu();
struct perf_event_attr *wd_attr;
struct perf_event *evt;
 
@@ -176,11 +176,13 @@ static int hardlockup_detector_event_create(void)
evt = perf_event_create_kernel_counter(wd_attr, cpu, NULL,
   watchdog_overflow_callback, 
NULL);
if (IS_ERR(evt)) {
+   put_cpu();
pr_debug("Perf event create on CPU %d failed with %ld\n", cpu,
 PTR_ERR(evt));
return PTR_ERR(evt);
}
this_cpu_write(watchdog_ev, evt);
+   put_cpu();
return 0;
 }
 
-- 
2.25.1



Re: [PATCH] arm64: Kconfig: Add SYS_SUPPORTS_APM_EMULATION

2020-12-16 Thread Lecopzer Chen
Hi Catalin,

Thanks for your reply.

so there is two points
1. out-of-tree function can't be approved
I totally agree with this :) so we may have a driver upstream in the future.
2. APM not make sense on arm64
Could you please let me konw the reason why APM on ARM64 doesn't make sense?


thanks!
BRs,
Lecopzer


> On Wed, Nov 25, 2020 at 07:41:30PM +0800, Lecopzer Chen wrote:
> > >> In order to select CONFIG_APM_EMULATION, make SYS_SUPPORTS_APM_EMULATION
> > >> default is y if ACPI isn't configured.
> > >
> > >I'm a bit confused why this should be enabled for !ACPI. Which DT
> > >platforms need this, and how do they use it? Why should this only be
> > >enabled for kernels without ACPI support, and not for kernels that
> > >support both ACPI and DT?
> > 
> > In our internal patch has no !ACPI here,
> > the reason I add here is that in kernel document[1] it mention:
> > > No, sorry, you cannot have both ACPI and APM enabled and running at once.
> > Thus, I try to limit the scope for who don't use the ACPI because I'm not 
> > sure
> > they could exist at the same time or not.
> > 
> > But I think it should be fine without !ACPI if APM and APCI
> > config won't conflict with each other.
> > 
> > So if it's better to remove !ACPI I'll send v2 for this.
> > 
> > BTW, The platform is for our internal kernel drivers, they utilize APM 
> > interface,
> > /dev/apm_bios to do their works in arm64.
> 
> Sorry, I don't think the APM interface makes sense on an arm64 kernel
> (and it's also used by an out of tree driver).


Re: [PATCH] arm64: Kconfig: Add SYS_SUPPORTS_APM_EMULATION

2020-12-14 Thread Lecopzer Chen
Hi,

Could any maintainer help review this?

Thanks a lot for your help,

BRs,
Lecopzer


> Although most of modern devices use ACPI, there still has combination
> of APM + ARM64.
> 
> In order to select CONFIG_APM_EMULATION, make SYS_SUPPORTS_APM_EMULATION
> default is y if ACPI isn't configured.
> 
> Signed-off-by: Lecopzer Chen 
> Suggested-by: YJ Chiang 
> ---
>  arch/arm64/Kconfig | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 1515f6f153a0..5e9e3694015a 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -260,6 +260,9 @@ config NO_IOPORT_MAP
>  config STACKTRACE_SUPPORT
>   def_bool y
>  
> +config SYS_SUPPORTS_APM_EMULATION
> + def_bool y if !ACPI
> +
>  config ILLEGAL_POINTER_VALUE
>   hex
>   default 0xdead





[PATCH] ARM: mm: harden branch predictor before opening interrupts during fault

2020-12-03 Thread Lecopzer Chen
This patch was send by "Sebastian Andrzej Siewior "
in [1] and rebase in v5.10-rc6.

The original commit message:

> On non-LPAE systems a write to 0xbff0 (modules area) from userland
> results in:
> | BUG: using smp_processor_id() in preemptible [] code: mem-tc/521
> | caller is __do_user_fault.constprop.2+0x4c/0x74
> | CPU: 1 PID: 521 Comm: mem-tc Not tainted 5.1.0-rc1 #4
> | [] (debug_smp_processor_id) from [] 
> (__do_user_fault.constprop.2+0x4c/0x74)
> | [] (__do_user_fault.constprop.2) from [] 
> (do_page_fault+0x278/0x37c)
> | [] (do_page_fault) from [] (do_DataAbort+0x3c/0xa8)
> | [] (do_DataAbort) from [] (__dabt_usr+0x3c/0x40)
>
> Move harden_branch_predictor() from __do_user_fault() to its both
> callers (do_bad_area() and do_page_fault()). The invocation in
> do_page_fault() is added before interrupst are enabled. The invocation
> in do_bad_area() is added just before __do_user_fault() is invoked.

The BUG still exists in v5.10-rc, and the previous disscussion was [2].
This issue can be easily reproduced in ARM with CONFIG_DEBUG_PREEMPT and
CONFIG_HARDEN_BRANCH_PREDICTOR by the following userspace program:

  int *p = 0x3ff4;
  *p = 123;

[1]:
https://patchwork.kernel.org/project/linux-arm-kernel/patch/20190319203239.gl46fxnfz6gze...@linutronix.de/
[2]:
https://lkml.org/lkml/2019/6/3/426

Fixes: f5fe12b1eaee2 ("ARM: spectre-v2: harden user aborts in kernel space")
Reported-by: Bernd Edlinger 
Signed-off-by: Sebastian Andrzej Siewior 
Signed-off-by: Lecopzer Chen 
Cc: YJ Chiang 
---
 arch/arm/mm/fault.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index efa402025031..f1b57b7d5a0c 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -138,9 +138,6 @@ __do_user_fault(unsigned long addr, unsigned int fsr, 
unsigned int sig,
 {
struct task_struct *tsk = current;
 
-   if (addr > TASK_SIZE)
-   harden_branch_predictor();
-
 #ifdef CONFIG_DEBUG_USER
if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
((user_debug & UDBG_BUS)  && (sig == SIGBUS))) {
@@ -173,8 +170,11 @@ void do_bad_area(unsigned long addr, unsigned int fsr, 
struct pt_regs *regs)
 * If we are in kernel mode at this point, we
 * have no context to handle this fault with.
 */
-   if (user_mode(regs))
+   if (user_mode(regs)) {
+   if (addr > TASK_SIZE)
+   harden_branch_predictor();
__do_user_fault(addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
+   }
else
__do_kernel_fault(mm, addr, fsr, regs);
 }
@@ -251,6 +251,9 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct 
pt_regs *regs)
tsk = current;
mm  = tsk->mm;
 
+   if (addr > TASK_SIZE && user_mode(regs))
+   harden_branch_predictor();
+
/* Enable interrupts if they were enabled in the parent context. */
if (interrupts_enabled(regs))
local_irq_enable();
-- 
2.18.0



Re: [PATCH] arm64: Kconfig: Add SYS_SUPPORTS_APM_EMULATION

2020-11-25 Thread Lecopzer Chen
>> From: "Lecopzer Chen" 
>> 
>> Although most of modern devices use ACPI, there still has combination
>> of APM + ARM64.
>> 
>> In order to select CONFIG_APM_EMULATION, make SYS_SUPPORTS_APM_EMULATION
>> default is y if ACPI isn't configured.
>
>I'm a bit confused why this should be enabled for !ACPI. Which DT
>platforms need this, and how do they use it? Why should this only be
>enabled for kernels without ACPI support, and not for kernels that
>support both ACPI and DT?
>
>Thanks,
>Mark.

Hi Mark,

In our internal patch has no !ACPI here,
the reason I add here is that in kernel document[1] it mention:
> No, sorry, you cannot have both ACPI and APM enabled and running at once.
Thus, I try to limit the scope for who don't use the ACPI because I'm not sure
they could exist at the same time or not.

But I think it should be fine without !ACPI if APM and APCI
config won't conflict with each other.

So if it's better to remove !ACPI I'll send v2 for this.


BTW, The platform is for our internal kernel drivers, they utilize APM 
interface,
/dev/apm_bios to do their works in arm64.





[1] APM or ACPI?:
https://www.kernel.org/doc/html/latest/power/apm-acpi.html


Thanks,
Lecopzer


>> 
>> Signed-off-by: Lecopzer Chen 
>> Suggested-by: YJ Chiang 
>> ---
>>  arch/arm64/Kconfig | 3 +++
>>  1 file changed, 3 insertions(+)
>> 
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index 1515f6f153a0..5e9e3694015a 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -260,6 +260,9 @@ config NO_IOPORT_MAP
>>  config STACKTRACE_SUPPORT
>>  def_bool y
>>  
>> +config SYS_SUPPORTS_APM_EMULATION
>> +def_bool y if !ACPI
>> +
>>  config ILLEGAL_POINTER_VALUE
>>  hex
>>  default 0xdead
>> -- 
>> 2.18.0
>> 


[PATCH] arm64: Kconfig: Add SYS_SUPPORTS_APM_EMULATION

2020-11-24 Thread Lecopzer Chen
From: "Lecopzer Chen" 

Although most of modern devices use ACPI, there still has combination
of APM + ARM64.

In order to select CONFIG_APM_EMULATION, make SYS_SUPPORTS_APM_EMULATION
default is y if ACPI isn't configured.

Signed-off-by: Lecopzer Chen 
Suggested-by: YJ Chiang 
---
 arch/arm64/Kconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1515f6f153a0..5e9e3694015a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -260,6 +260,9 @@ config NO_IOPORT_MAP
 config STACKTRACE_SUPPORT
def_bool y
 
+config SYS_SUPPORTS_APM_EMULATION
+   def_bool y if !ACPI
+
 config ILLEGAL_POINTER_VALUE
hex
default 0xdead
-- 
2.18.0



[PATCH] mm/cma.c: remove redundant cma_mutex lock

2020-10-20 Thread Lecopzer Chen
The cma_mutex which protects alloc_contig_range() was first appeared in
commit 7ee793a62fa8c ("cma: Remove potential deadlock situation"),
at that time, there is no guarantee the behavior of concurrency inside
alloc_contig_range().

After the commit 2c7452a075d4db2dc
("mm/page_isolation.c: make start_isolate_page_range() fail if already 
isolated")
  > However, two subsystems (CMA and gigantic
  > huge pages for example) could attempt operations on the same range.  If
  > this happens, one thread may 'undo' the work another thread is doing.
  > This can result in pageblocks being incorrectly left marked as
  > MIGRATE_ISOLATE and therefore not available for page allocation.
The concurrency inside alloc_contig_range() was clarified.

Now we can find that hugepage and virtio call alloc_contig_range() without
any lock, thus cma_mutex is "redundant" in cma_alloc() now.

Signed-off-by: Lecopzer Chen 
---
 mm/cma.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/mm/cma.c b/mm/cma.c
index 7f415d7cda9f..3692a34e2353 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -38,7 +38,6 @@
 
 struct cma cma_areas[MAX_CMA_AREAS];
 unsigned cma_area_count;
-static DEFINE_MUTEX(cma_mutex);
 
 phys_addr_t cma_get_base(const struct cma *cma)
 {
@@ -454,10 +453,9 @@ struct page *cma_alloc(struct cma *cma, size_t count, 
unsigned int align,
mutex_unlock(>lock);
 
pfn = cma->base_pfn + (bitmap_no << cma->order_per_bit);
-   mutex_lock(_mutex);
ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA,
 GFP_KERNEL | (no_warn ? __GFP_NOWARN : 0));
-   mutex_unlock(_mutex);
+
if (ret == 0) {
page = pfn_to_page(pfn);
break;
-- 
2.18.0


Re: [PATCH 0/3] arm64: perf: Add support for Perf NMI interrupts

2020-05-18 Thread Lecopzer Chen
HI Sumit,

Thanks for your information.

I've already implemented IPI (same as you did [1], little difference
in detail), hardlockup detector and perf in last year(2019) for
debuggability.
And now we tend to upstream to reduce kernel maintaining effort.
I'm glad if someone in ARM can do this work :)

Hi Julien,

Does any Arm maintainers can proceed this action?
This is really useful in debugging.
Thank you!!



[1] https://lkml.org/lkml/2020/4/24/328


Lecopzer

Sumit Garg  於 2020年5月18日 週一 下午1:46寫道:
>
> + Julien
>
> Hi Lecopzer,
>
> On Sat, 16 May 2020 at 18:20, Lecopzer Chen  wrote:
> >
> > These series implement Perf NMI funxtionality and depends on
> > Pseudo NMI [1] which has been upstreamed.
> >
> > In arm64 with GICv3, Pseudo NMI was implemented for NMI-like interruts.
> > That can be extended to Perf NMI which is the prerequisite for hard-lockup
> > detector which had already a standard interface inside Linux.
> >
> > Thus the first step we need to implement perf NMI interface and make sure
> > it works fine.
> >
>
> This is something that is already implemented via Julien's patch-set
> [1]. Its v4 has been floating since July, 2019 and I couldn't find any
> major blocking comments but not sure why things haven't progressed
> further.
>
> Maybe Julien or Arm maintainers can provide updates on existing
> patch-set [1] and how we should proceed further with this interesting
> feature.
>
> And regarding hard-lockup detection, I have been able to enable it
> based on perf NMI events using Julien's perf patch-set [1]. Have a
> look at the patch here [2].
>
> [1] https://patchwork.kernel.org/cover/11047407/
> [2] http://lists.infradead.org/pipermail/linux-arm-kernel/2020-May/732227.html
>
> -Sumit
>
> > Perf NMI has been test by dd if=/dev/urandom of=/dev/null like the link [2]
> > did.
> >
> > [1] https://lkml.org/lkml/2019/1/31/535
> > [2] https://www.linaro.org/blog/debugging-arm-kernels-using-nmifiq
> >
> >
> > Lecopzer Chen (3):
> >   arm_pmu: Add support for perf NMI interrupts registration
> >   arm64: perf: Support NMI context for perf event ISR
> >   arm64: Kconfig: Add support for the Perf NMI
> >
> >  arch/arm64/Kconfig | 10 +++
> >  arch/arm64/kernel/perf_event.c | 36 ++--
> >  drivers/perf/arm_pmu.c | 51 ++
> >  include/linux/perf/arm_pmu.h   |  6 
> >  4 files changed, 88 insertions(+), 15 deletions(-)
> >
> > --
> > 2.25.1
> >
> >
> > ___
> > linux-arm-kernel mailing list
> > linux-arm-ker...@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


Re: [PATCH 1/3] arm_pmu: Add support for perf NMI interrupts registration

2020-05-17 Thread Lecopzer Chen
There was some mistakes when merging this patch.
The free nmi part is not present :(

The following part will be added in V2 next weekend.

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index fa37b72d19e2..aa9ed09e5303 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -544,6 +544,38 @@ static int armpmu_count_irq_users(const int irq)
return count;
 }

+static void armpmu_teardown_percpu_nmi_other(void* info)
+{
+   /*
+* We don't need to disable preemption since smp_call_function()
+* did this for us.
+*/
+   teardown_percpu_nmi((uintptr_t) info);
+}
+
+static void _armpmu_free_irq(unsigned int irq, void *dev_id)
+{
+   if (armpmu_support_nmi())
+   free_nmi(irq, dev_id);
+   else
+   free_irq(irq, dev_id);
+}
+
+static void _armpmu_free_percpu_irq(unsigned int irq, void __percpu *dev_id)
+{
+   if (armpmu_support_nmi()) {
+   preempt_disable();
+   teardown_percpu_nmi(irq);
+   smp_call_function(armpmu_teardown_percpu_nmi_other,
+ (void *)(uintptr_t) irq, true);
+   preempt_enable();
+
+   free_percpu_nmi(irq, dev_id);
+   }
+   else
+   free_percpu_irq(irq, dev_id);
+}
+
 void armpmu_free_irq(int irq, int cpu)
 {
if (per_cpu(cpu_irq, cpu) == 0)
@@ -552,9 +584,9 @@ void armpmu_free_irq(int irq, int cpu)
return;

if (!irq_is_percpu_devid(irq))
-   free_irq(irq, per_cpu_ptr(_armpmu, cpu));
+   _armpmu_free_irq(irq, per_cpu_ptr(_armpmu, cpu));
else if (armpmu_count_irq_users(irq) == 1)
-   free_percpu_irq(irq, _armpmu);
+   _armpmu_free_percpu_irq(irq, _armpmu);

per_cpu(cpu_irq, cpu) = 0;
 }




Thanks,
Lecopzer

Lecopzer Chen  於 2020年5月16日 週六 下午8:50寫道:
>
> Register perf interrupts by request_nmi()/percpu_nmi() when both
> ARM64_PSEUDO_NMI and ARM64_PSEUDO_NMI_PERF are enabled and nmi
> cpufreature is active.
>
> Signed-off-by: Lecopzer Chen 
> ---
>  drivers/perf/arm_pmu.c   | 51 +++-
>  include/linux/perf/arm_pmu.h |  6 +
>  2 files changed, 51 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
> index df352b334ea7..fa37b72d19e2 100644
> --- a/drivers/perf/arm_pmu.c
> +++ b/drivers/perf/arm_pmu.c
> @@ -559,6 +559,48 @@ void armpmu_free_irq(int irq, int cpu)
> per_cpu(cpu_irq, cpu) = 0;
>  }
>
> +static void armpmu_prepare_percpu_nmi_other(void *info)
> +{
> +   /*
> +* We don't need to disable preemption since smp_call_function()
> +* did this for us.
> +*/
> +   prepare_percpu_nmi((uintptr_t) info);
> +}
> +
> +static int _armpmu_request_irq(unsigned int irq, irq_handler_t handler,
> +  unsigned long flags, int cpu)
> +{
> +   if (armpmu_support_nmi())
> +   return request_nmi(irq, handler, flags, "arm-pmu",
> +  per_cpu_ptr(_armpmu, cpu));
> +   return request_irq(irq, handler, flags, "arm-pmu",
> +  per_cpu_ptr(_armpmu, cpu));
> +}
> +
> +static int _armpmu_request_percpu_irq(unsigned int irq, irq_handler_t 
> handler)
> +{
> +   if (armpmu_support_nmi()) {
> +   int err;
> +
> +   err = request_percpu_nmi(irq, handler, "arm-pmu",
> +_armpmu);
> +   if (err)
> +   return err;
> +
> +   preempt_disable();
> +   err = prepare_percpu_nmi(irq);
> +   if (err) {
> +   return err;
> +   preempt_enable();
> +   }
> +   smp_call_function(armpmu_prepare_percpu_nmi_other,
> + (void *)(uintptr_t) irq, true);
> +   preempt_enable();
> +   }
> +   return request_percpu_irq(irq, handler, "arm-pmu",
> + _armpmu);
> +}
> +
>  int armpmu_request_irq(int irq, int cpu)
>  {
> int err = 0;
> @@ -582,12 +624,9 @@ int armpmu_request_irq(int irq, int cpu)
> IRQF_NO_THREAD;
>
> irq_set_status_flags(irq, IRQ_NOAUTOEN);
> -   err = request_irq(irq, handler, irq_flags, "arm-pmu",
> - per_cpu_ptr(_armpmu, cpu));
> -   } else if (armpmu_count_irq_users(irq) == 0) {
> -   err = request_percpu_irq(irq, handler, "arm-pmu",
> -_armpmu);
> -   }
> +   err = _armpmu_

[PATCH 1/3] arm_pmu: Add support for perf NMI interrupts registration

2020-05-16 Thread Lecopzer Chen
Register perf interrupts by request_nmi()/percpu_nmi() when both
ARM64_PSEUDO_NMI and ARM64_PSEUDO_NMI_PERF are enabled and nmi
cpufreature is active.

Signed-off-by: Lecopzer Chen 
---
 drivers/perf/arm_pmu.c   | 51 +++-
 include/linux/perf/arm_pmu.h |  6 +
 2 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index df352b334ea7..fa37b72d19e2 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -559,6 +559,48 @@ void armpmu_free_irq(int irq, int cpu)
per_cpu(cpu_irq, cpu) = 0;
 }
 
+static void armpmu_prepare_percpu_nmi_other(void *info)
+{
+   /*
+* We don't need to disable preemption since smp_call_function()
+* did this for us.
+*/
+   prepare_percpu_nmi((uintptr_t) info);
+}
+
+static int _armpmu_request_irq(unsigned int irq, irq_handler_t handler,
+  unsigned long flags, int cpu)
+{
+   if (armpmu_support_nmi())
+   return request_nmi(irq, handler, flags, "arm-pmu",
+  per_cpu_ptr(_armpmu, cpu));
+   return request_irq(irq, handler, flags, "arm-pmu",
+  per_cpu_ptr(_armpmu, cpu));
+}
+
+static int _armpmu_request_percpu_irq(unsigned int irq, irq_handler_t handler)
+{
+   if (armpmu_support_nmi()) {
+   int err;
+
+   err = request_percpu_nmi(irq, handler, "arm-pmu",
+_armpmu);
+   if (err)
+   return err;
+
+   preempt_disable();
+   err = prepare_percpu_nmi(irq);
+   if (err) {
+   return err;
+   preempt_enable();
+   }
+   smp_call_function(armpmu_prepare_percpu_nmi_other,
+ (void *)(uintptr_t) irq, true);
+   preempt_enable();
+   }
+   return request_percpu_irq(irq, handler, "arm-pmu",
+ _armpmu);
+}
+
 int armpmu_request_irq(int irq, int cpu)
 {
int err = 0;
@@ -582,12 +624,9 @@ int armpmu_request_irq(int irq, int cpu)
IRQF_NO_THREAD;
 
irq_set_status_flags(irq, IRQ_NOAUTOEN);
-   err = request_irq(irq, handler, irq_flags, "arm-pmu",
- per_cpu_ptr(_armpmu, cpu));
-   } else if (armpmu_count_irq_users(irq) == 0) {
-   err = request_percpu_irq(irq, handler, "arm-pmu",
-_armpmu);
-   }
+   err = _armpmu_request_irq(irq, handler, irq_flags, cpu);
+   } else if (armpmu_count_irq_users(irq) == 0)
+   err = _armpmu_request_percpu_irq(irq, handler);
 
if (err)
goto err_out;
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h
index 5b616dde9a4c..5b878b5a22aa 100644
--- a/include/linux/perf/arm_pmu.h
+++ b/include/linux/perf/arm_pmu.h
@@ -160,6 +160,12 @@ int arm_pmu_acpi_probe(armpmu_init_fn init_fn);
 static inline int arm_pmu_acpi_probe(armpmu_init_fn init_fn) { return 0; }
 #endif
 
+static inline bool armpmu_support_nmi(void)
+{
+   return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI_PERF) &&
+  system_uses_irq_prio_masking();
+}
+
 /* Internal functions only for core arm_pmu code */
 struct arm_pmu *armpmu_alloc(void);
 struct arm_pmu *armpmu_alloc_atomic(void);
-- 
2.25.1



[PATCH 2/3] arm64: perf: Support NMI context for perf event ISR

2020-05-16 Thread Lecopzer Chen
Perf ISR doesn't support for NMI context, thus add some necessary
condition-if to handle NMI context:

- We should not hold pmu_lock since it may have already been acquired
before NMI triggered.
- irq_work should not run at NMI context.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/kernel/perf_event.c | 36 +-
 1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 4d7879484cec..94b404509f02 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -313,6 +313,23 @@ static inline bool armv8pmu_event_is_chained(struct 
perf_event *event)
   (idx != ARMV8_IDX_CYCLE_COUNTER);
 }
 
+/*
+ * NMI Perf interrupts may be triggered during kernel holding
+ * same lock.
+ * Avoid acquiring lock again in NMI context.
+ */
+#define armv8pmu_lock(lock, flags) \
+   do {\
+   if (!in_nmi())  \
+   raw_spin_lock_irqsave(lock, flags); \
+   } while (0)
+
+#define armv8pmu_unlock(lock, flags)   \
+   do {\
+   if (!in_nmi())  \
+   raw_spin_unlock_irqrestore(lock, flags);\
+   } while (0)
+
 /*
  * ARMv8 low level PMU access
  */
@@ -589,7 +606,7 @@ static void armv8pmu_enable_event(struct perf_event *event)
 * Enable counter and interrupt, and set the counter to count
 * the event that we're interested in.
 */
-   raw_spin_lock_irqsave(>pmu_lock, flags);
+   armv8pmu_lock(>pmu_lock, flags);
 
/*
 * Disable counter
@@ -611,7 +628,7 @@ static void armv8pmu_enable_event(struct perf_event *event)
 */
armv8pmu_enable_event_counter(event);
 
-   raw_spin_unlock_irqrestore(>pmu_lock, flags);
+   armv8pmu_unlock(>pmu_lock, flags);
 }
 
 static void armv8pmu_disable_event(struct perf_event *event)
@@ -623,7 +640,7 @@ static void armv8pmu_disable_event(struct perf_event *event)
/*
 * Disable counter and interrupt
 */
-   raw_spin_lock_irqsave(>pmu_lock, flags);
+   armv8pmu_lock(>pmu_lock, flags);
 
/*
 * Disable counter
@@ -635,7 +652,7 @@ static void armv8pmu_disable_event(struct perf_event *event)
 */
armv8pmu_disable_event_irq(event);
 
-   raw_spin_unlock_irqrestore(>pmu_lock, flags);
+   armv8pmu_unlock(>pmu_lock, flags);
 }
 
 static void armv8pmu_start(struct arm_pmu *cpu_pmu)
@@ -643,10 +660,10 @@ static void armv8pmu_start(struct arm_pmu *cpu_pmu)
unsigned long flags;
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
-   raw_spin_lock_irqsave(>pmu_lock, flags);
+   armv8pmu_lock(>pmu_lock, flags);
/* Enable all counters */
armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMU_PMCR_E);
-   raw_spin_unlock_irqrestore(>pmu_lock, flags);
+   armv8pmu_unlock(>pmu_lock, flags);
 }
 
 static void armv8pmu_stop(struct arm_pmu *cpu_pmu)
@@ -654,10 +671,10 @@ static void armv8pmu_stop(struct arm_pmu *cpu_pmu)
unsigned long flags;
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
 
-   raw_spin_lock_irqsave(>pmu_lock, flags);
+   armv8pmu_lock(>pmu_lock, flags);
/* Disable all counters */
armv8pmu_pmcr_write(armv8pmu_pmcr_read() & ~ARMV8_PMU_PMCR_E);
-   raw_spin_unlock_irqrestore(>pmu_lock, flags);
+   armv8pmu_unlock(>pmu_lock, flags);
 }
 
 static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu)
@@ -722,7 +739,8 @@ static irqreturn_t armv8pmu_handle_irq(struct arm_pmu 
*cpu_pmu)
 * platforms that can have the PMU interrupts raised as an NMI, this
 * will not work.
 */
-   irq_work_run();
+   if (!armpmu_support_nmi())
+   irq_work_run();
 
return IRQ_HANDLED;
 }
-- 
2.25.1



[PATCH 3/3] arm64: Kconfig: Add support for the Perf NMI

2020-05-16 Thread Lecopzer Chen
This is an extending function for Pseudo NMI that registering
Perf events interrupts as NMI.

It's helpful for sampling irq-off context when using perf.

Signed-off-by: Lecopzer Chen 
---
 arch/arm64/Kconfig | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 40fb05d96c60..f89c169771a0 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1679,6 +1679,16 @@ config ARM64_PSEUDO_NMI
  If unsure, say N
 
 if ARM64_PSEUDO_NMI
+config ARM64_PSEUDO_NMI_PERF
+   bool "Register Perf interrupts as Pseudo NMI"
+   depends on HW_PERF_EVENTS
+   depends on ARM_PMU
+   select HAVE_PERF_EVENTS_NMI
+   help
+ This registers Perf interrupts to NMI when Pseudo NMI is active.
+ This option is helpful when you need to debug any context disabled
+ irq and get more inforamtion.
+
+ If unsure, say N
+
 config ARM64_DEBUG_PRIORITY_MASKING
bool "Debug interrupt priority masking"
help
-- 
2.25.1



[PATCH 0/3] arm64: perf: Add support for Perf NMI interrupts

2020-05-16 Thread Lecopzer Chen
These series implement Perf NMI funxtionality and depends on
Pseudo NMI [1] which has been upstreamed.

In arm64 with GICv3, Pseudo NMI was implemented for NMI-like interruts.
That can be extended to Perf NMI which is the prerequisite for hard-lockup
detector which had already a standard interface inside Linux.

Thus the first step we need to implement perf NMI interface and make sure
it works fine.

Perf NMI has been test by dd if=/dev/urandom of=/dev/null like the link [2]
did.

[1] https://lkml.org/lkml/2019/1/31/535
[2] https://www.linaro.org/blog/debugging-arm-kernels-using-nmifiq


Lecopzer Chen (3):
  arm_pmu: Add support for perf NMI interrupts registration
  arm64: perf: Support NMI context for perf event ISR
  arm64: Kconfig: Add support for the Perf NMI

 arch/arm64/Kconfig | 10 +++
 arch/arm64/kernel/perf_event.c | 36 ++--
 drivers/perf/arm_pmu.c | 51 ++
 include/linux/perf/arm_pmu.h   |  6 
 4 files changed, 88 insertions(+), 15 deletions(-)

-- 
2.25.1



[PATCH] staging: android: ion: Remove unused rbtree for ion_buffer

2019-07-12 Thread Lecopzer Chen
ion_buffer_add() insert ion_buffer into rbtree every time creating
an ion_buffer but never use it after ION reworking.
Also, buffer_lock protects only rbtree operation, remove it together.

Signed-off-by: Lecopzer Chen 
Cc: YJ Chiang 
Cc: Lecopzer Chen 
---
 drivers/staging/android/ion/ion.c | 36 ---
 drivers/staging/android/ion/ion.h | 10 +
 2 files changed, 1 insertion(+), 45 deletions(-)

diff --git a/drivers/staging/android/ion/ion.c 
b/drivers/staging/android/ion/ion.c
index 92c2914239e3..e6b1ca141b93 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -29,32 +29,6 @@
 static struct ion_device *internal_dev;
 static int heap_id;
 
-/* this function should only be called while dev->lock is held */
-static void ion_buffer_add(struct ion_device *dev,
-  struct ion_buffer *buffer)
-{
-   struct rb_node **p = >buffers.rb_node;
-   struct rb_node *parent = NULL;
-   struct ion_buffer *entry;
-
-   while (*p) {
-   parent = *p;
-   entry = rb_entry(parent, struct ion_buffer, node);
-
-   if (buffer < entry) {
-   p = &(*p)->rb_left;
-   } else if (buffer > entry) {
-   p = &(*p)->rb_right;
-   } else {
-   pr_err("%s: buffer already found.", __func__);
-   BUG();
-   }
-   }
-
-   rb_link_node(>node, parent, p);
-   rb_insert_color(>node, >buffers);
-}
-
 /* this function should only be called while dev->lock is held */
 static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
struct ion_device *dev,
@@ -100,9 +74,6 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap 
*heap,
 
INIT_LIST_HEAD(>attachments);
mutex_init(>lock);
-   mutex_lock(>buffer_lock);
-   ion_buffer_add(dev, buffer);
-   mutex_unlock(>buffer_lock);
return buffer;
 
 err1:
@@ -131,11 +102,6 @@ void ion_buffer_destroy(struct ion_buffer *buffer)
 static void _ion_buffer_destroy(struct ion_buffer *buffer)
 {
struct ion_heap *heap = buffer->heap;
-   struct ion_device *dev = buffer->dev;
-
-   mutex_lock(>buffer_lock);
-   rb_erase(>node, >buffers);
-   mutex_unlock(>buffer_lock);
 
if (heap->flags & ION_HEAP_FLAG_DEFER_FREE)
ion_heap_freelist_add(heap, buffer);
@@ -694,8 +660,6 @@ static int ion_device_create(void)
}
 
idev->debug_root = debugfs_create_dir("ion", NULL);
-   idev->buffers = RB_ROOT;
-   mutex_init(>buffer_lock);
init_rwsem(>lock);
plist_head_init(>heaps);
internal_dev = idev;
diff --git a/drivers/staging/android/ion/ion.h 
b/drivers/staging/android/ion/ion.h
index e291299fd35f..74914a266e25 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -23,7 +23,6 @@
 
 /**
  * struct ion_buffer - metadata for a particular buffer
- * @node:  node in the ion_device buffers tree
  * @list:  element in list of deferred freeable buffers
  * @dev:   back pointer to the ion_device
  * @heap:  back pointer to the heap the buffer came from
@@ -39,10 +38,7 @@
  * @attachments:   list of devices attached to this buffer
  */
 struct ion_buffer {
-   union {
-   struct rb_node node;
-   struct list_head list;
-   };
+   struct list_head list;
struct ion_device *dev;
struct ion_heap *heap;
unsigned long flags;
@@ -61,14 +57,10 @@ void ion_buffer_destroy(struct ion_buffer *buffer);
 /**
  * struct ion_device - the metadata of the ion device node
  * @dev:   the actual misc device
- * @buffers:   an rb tree of all the existing buffers
- * @buffer_lock:   lock protecting the tree of buffers
  * @lock:  rwsem protecting the tree of heaps and clients
  */
 struct ion_device {
struct miscdevice dev;
-   struct rb_root buffers;
-   struct mutex buffer_lock;
struct rw_semaphore lock;
struct plist_head heaps;
struct dentry *debug_root;
-- 
2.17.1



[PATCH] mm/sparse: fix ALIGN() without power of 2 in sparse_buffer_alloc()

2019-07-05 Thread Lecopzer Chen
The size argumnet passed into sparse_buffer_alloc() has already
aligned with PAGE_SIZE or PMD_SIZE.

If the size after aligned is not power of 2 (e.g. 0x48), the
PTR_ALIGN() will return wrong value.
Use roundup to round sparsemap_buf up to next multiple of size.

Signed-off-by: Lecopzer Chen 
Signed-off-by: Mark-PK Tsai 
Cc: YJ Chiang 
Cc: Lecopzer Chen 
Cc: Andrew Morton 
Cc: Pavel Tatashin 
Cc: Oscar Salvador 
Cc: Michal Hocko 
Cc: Mike Rapoport 
Cc: linux-kernel@vger.kernel.org
---
 mm/sparse.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/sparse.c b/mm/sparse.c
index 2b3b5be85120..dafd130f9a55 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -459,7 +459,7 @@ void * __meminit sparse_buffer_alloc(unsigned long size)
void *ptr = NULL;
 
if (sparsemap_buf) {
-   ptr = PTR_ALIGN(sparsemap_buf, size);
+   ptr = (void *) roundup((unsigned long)sparsemap_buf, size);
if (ptr + size > sparsemap_buf_end)
ptr = NULL;
else {
-- 
2.18.0



[PATCH] mm/sparse: fix memory leak of sparsemap_buf in aliged memory

2019-07-05 Thread Lecopzer Chen
sparse_buffer_alloc(size) get size of memory from sparsemap_buf after
being aligned with the size. However, the size is at least
PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION) and usually larger
than PAGE_SIZE.
Also, the Sparse_buffer_fini() only frees memory between
sparsemap_buf and sparsemap_buf_end, since sparsemap_buf may be changed
by PTR_ALIGN() first, the aligned space before sparsemap_buf is
wasted and no one will touch it.

In our ARM32 platform (without SPARSEMEM_VMEMMAP)
  Sparse_buffer_init
Reserve d359c000 - d3e9c000 (9M)
  Sparse_buffer_alloc
Alloc   d3a0 - d3E8 (4.5M)
  Sparse_buffer_fini
Freed3e8 - d3e9c000 (~=100k)
 The reserved memory between d359c000 - d3a0 (~=4.4M) is unfreed.

In ARM64 platform (with SPARSEMEM_VMEMMAP)

  sparse_buffer_init
Reserve ffc07d623000 - ffc07f623000 (32M)
  Sparse_buffer_alloc
Alloc   ffc07d80 - ffc07f60 (30M)
  Sparse_buffer_fini
Freeffc07f60 - ffc07f623000 (140K)
 The reserved memory between ffc07d623000 - ffc07d80
 (~=1.9M) is unfreed.

Let explicit free redundant aligned memory.

Signed-off-by: Lecopzer Chen 
Signed-off-by: Mark-PK Tsai 
Cc: YJ Chiang 
Cc: Lecopzer Chen 
Cc: Andrew Morton 
Cc: Pavel Tatashin 
Cc: Oscar Salvador 
Cc: Michal Hocko 
Cc: Mike Rapoport 
Cc: linux-kernel@vger.kernel.org
---
 mm/sparse.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/mm/sparse.c b/mm/sparse.c
index fd13166949b5..2b3b5be85120 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -428,6 +428,12 @@ struct page __init *sparse_mem_map_populate(unsigned long 
pnum, int nid,
 static void *sparsemap_buf __meminitdata;
 static void *sparsemap_buf_end __meminitdata;
 
+static inline void __init sparse_buffer_free(unsigned long size)
+{
+   WARN_ON(!sparsemap_buf || size == 0);
+   memblock_free_early(__pa(sparsemap_buf), size);
+}
+
 static void __init sparse_buffer_init(unsigned long size, int nid)
 {
phys_addr_t addr = __pa(MAX_DMA_ADDRESS);
@@ -444,7 +450,7 @@ static void __init sparse_buffer_fini(void)
unsigned long size = sparsemap_buf_end - sparsemap_buf;
 
if (sparsemap_buf && size > 0)
-   memblock_free_early(__pa(sparsemap_buf), size);
+   sparse_buffer_free(size);
sparsemap_buf = NULL;
 }
 
@@ -456,8 +462,12 @@ void * __meminit sparse_buffer_alloc(unsigned long size)
ptr = PTR_ALIGN(sparsemap_buf, size);
if (ptr + size > sparsemap_buf_end)
ptr = NULL;
-   else
+   else {
+   /* Free redundant aligned space */
+   if ((unsigned long)(ptr - sparsemap_buf) > 0)
+   sparse_buffer_free((unsigned long)(ptr - 
sparsemap_buf));
sparsemap_buf = ptr + size;
+   }
}
return ptr;
 }
-- 
2.18.0



Re: [PATCH] test_power: Add CURRENT and CHARGE_COUNTER properties

2019-06-25 Thread Lecopzer Chen
Dear Sebastian,

Thanks for your review and helpful suggestion,
Since our platform is relative simple, I just miss the part you refer to.

I will fix them in patch v2.


Thanks,
Lecopzer


Re: [PATCH] test_power: Add CURRENT and CHARGE_COUNTER properties

2019-06-25 Thread Lecopzer Chen
Dear Sebastian,

Thanks for your review and helpful suggestion,
Since our platform is relative simple, I just miss the part you refer to.

I will fix them in patch v2.


Thanks,
Lecopzer


Re: [PATCH] genirq: Remove warning on preemptible in prepare_percpu_nmi()

2019-06-20 Thread Lecopzer Chen
Thanks a lot for reply!!

I just misunderstood how a PPI is registered and thought
I have a chance to eliminate the code.
This patch seems nonsense now, please ignore it.

Sorry to disturb you guys.


Thanks,
Lecopzer


[PATCH] genirq: Remove warning on preemptible in prepare_percpu_nmi()

2019-06-20 Thread Lecopzer Chen
prepare_percpu_nmi() acquires lock first by irq_get_desc_lock(),
no matter whether preempt enabled or not, acquiring lock forces preempt off.

This simplifies the usage of prepare_percpu_nmi() and we don't need to
acquire extra lock or explicitly call preempt_[disable,enable]().

Signed-off-by: Lecopzer Chen 
Cc: Thomas Gleixner 
Cc: Peter Zijlstra 
Cc: Ingo Molnar 
Cc: Marc Zyngier 
Cc: Julien Thierry 
Cc: YJ Chiang 
Cc: Lecopzer Chen 
---
 kernel/irq/manage.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 78f3ddeb7fe4..aa03640cd7fb 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2509,9 +2509,6 @@ int request_percpu_nmi(unsigned int irq, irq_handler_t 
handler,
  * This call prepares an interrupt line to deliver NMI on the current CPU,
  * before that interrupt line gets enabled with enable_percpu_nmi().
  *
- * As a CPU local operation, this should be called from non-preemptible
- * context.
- *
  * If the interrupt line cannot be used to deliver NMIs, function
  * will fail returning a negative value.
  */
@@ -2521,8 +2518,6 @@ int prepare_percpu_nmi(unsigned int irq)
struct irq_desc *desc;
int ret = 0;
 
-   WARN_ON(preemptible());
-
desc = irq_get_desc_lock(irq, ,
 IRQ_GET_DESC_CHECK_PERCPU);
if (!desc)
@@ -2554,17 +2549,12 @@ int prepare_percpu_nmi(unsigned int irq)
  * This call undoes the setup done by prepare_percpu_nmi().
  *
  * IRQ line should not be enabled for the current CPU.
- *
- * As a CPU local operation, this should be called from non-preemptible
- * context.
  */
 void teardown_percpu_nmi(unsigned int irq)
 {
unsigned long flags;
struct irq_desc *desc;
 
-   WARN_ON(preemptible());
-
desc = irq_get_desc_lock(irq, ,
 IRQ_GET_DESC_CHECK_PERCPU);
if (!desc)
-- 
2.18.0



[PATCH] test_power: Add CURRENT and CHARGE_COUNTER properties

2019-05-14 Thread Lecopzer Chen
From: "Lecopzer Chen" 

Emulate battery current (variable) and battery CHARGE_COUNTER
(same as battery_capacity) properties.

Signed-off-by: Lecopzer Chen 
Cc: YJ Chiang 

---
 drivers/power/supply/test_power.c | 33 +++
 1 file changed, 33 insertions(+)

diff --git a/drivers/power/supply/test_power.c 
b/drivers/power/supply/test_power.c
index 57246cdbd042..9f85060c84de 100644
--- a/drivers/power/supply/test_power.c
+++ b/drivers/power/supply/test_power.c
@@ -36,6 +36,7 @@ static int battery_present= 1; /* true */
 static int battery_technology  = POWER_SUPPLY_TECHNOLOGY_LION;
 static int battery_capacity= 50;
 static int battery_voltage = 3300;
+static int battery_current = 1600;
 
 static bool module_initialized;
 
@@ -101,6 +102,7 @@ static int test_power_get_battery_property(struct 
power_supply *psy,
break;
case POWER_SUPPLY_PROP_CAPACITY:
case POWER_SUPPLY_PROP_CHARGE_NOW:
+   case POWER_SUPPLY_PROP_CHARGE_COUNTER:
val->intval = battery_capacity;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
@@ -117,6 +119,10 @@ static int test_power_get_battery_property(struct 
power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
val->intval = battery_voltage;
break;
+   case POWER_SUPPLY_PROP_CURRENT_AVG:
+   case POWER_SUPPLY_PROP_CURRENT_NOW:
+   val->intval = battery_current;
+   break;
default:
pr_info("%s: some properties deliberately report errors.\n",
__func__);
@@ -138,6 +144,7 @@ static enum power_supply_property 
test_power_battery_props[] = {
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_NOW,
+   POWER_SUPPLY_PROP_CHARGE_COUNTER,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -147,6 +154,8 @@ static enum power_supply_property 
test_power_battery_props[] = {
POWER_SUPPLY_PROP_SERIAL_NUMBER,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
+   POWER_SUPPLY_PROP_CURRENT_AVG,
+   POWER_SUPPLY_PROP_CURRENT_NOW,
 };
 
 static char *test_power_ac_supplied_to[] = {
@@ -450,6 +459,21 @@ static int param_set_battery_voltage(const char *key,
 
 #define param_get_battery_voltage param_get_int
 
+static int param_set_battery_current(const char *key,
+   const struct kernel_param *kp)
+{
+   int tmp;
+
+   if (1 != sscanf(key, "%d", ))
+   return -EINVAL;
+
+   battery_current = tmp;
+   signal_power_supply_changed(test_power_supplies[TEST_BATTERY]);
+   return 0;
+}
+
+#define param_get_battery_current param_get_int
+
 static const struct kernel_param_ops param_ops_ac_online = {
.set = param_set_ac_online,
.get = param_get_ac_online,
@@ -490,6 +514,11 @@ static const struct kernel_param_ops 
param_ops_battery_voltage = {
.get = param_get_battery_voltage,
 };
 
+static const struct kernel_param_ops param_ops_battery_current = {
+   .set = param_set_battery_current,
+   .get = param_get_battery_current,
+};
+
 #define param_check_ac_online(name, p) __param_check(name, p, void);
 #define param_check_usb_online(name, p) __param_check(name, p, void);
 #define param_check_battery_status(name, p) __param_check(name, p, void);
@@ -498,6 +527,7 @@ static const struct kernel_param_ops 
param_ops_battery_voltage = {
 #define param_check_battery_health(name, p) __param_check(name, p, void);
 #define param_check_battery_capacity(name, p) __param_check(name, p, void);
 #define param_check_battery_voltage(name, p) __param_check(name, p, void);
+#define param_check_battery_current(name, p) __param_check(name, p, void);
 
 
 module_param(ac_online, ac_online, 0644);
@@ -528,6 +558,9 @@ MODULE_PARM_DESC(battery_capacity, "battery capacity 
(percentage)");
 module_param(battery_voltage, battery_voltage, 0644);
 MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)");
 
+module_param(battery_current, battery_current, 0644);
+MODULE_PARM_DESC(battery_current, "battery current (milliampere)");
+
 MODULE_DESCRIPTION("Power supply driver for testing");
 MODULE_AUTHOR("Anton Vorontsov ");
 MODULE_LICENSE("GPL");
-- 
2.18.0