From: Mike Rapoport <r...@linux.ibm.com>

Hi,

This is yet another attempt to enable SPARSEMEM on ARC.

I've boot tested it on nSIM with haps_hs_defconfig with highmem and
sparsemem enabled.

With sparsemem the kernel text becomes a bit smaller, but bss and data are
slightly increased:

$ size discontig/vmlinux sparse/vmlinux
   text    data     bss     dec     hex filename
4429390  785456  244580 5459426  534de2 discontig/vmlinux
4415099  786224  244844 5446167  531a17 sparse/vmlinux

I've also added a dummy global functions to wrap pfn_valid(), page_to_pfn()
and pfn_to_page(). Judging by objdump, sparsemem is a bit more efficient:

        DISCONTIGMEM                    SPARSEMEM
<pfn_to_page>:
        seths   r2,0x3ffff,r0           lsr     r2,r0,0xe
        mpy     r2,r2,1896              mpy     r0,r0,0x24
        add     r3,r2,0x8050066c        add3    r2,0x80529d1c,r2
        add_s   r2,r2,0x80500668        ld_s    r2,[r2,0]
        ld_s    r3,[r3,0]               bmskn   r2,r2,0x3
        sub_s   r0,r0,r3                j_s.d   [blink]
        ld_s    r2,[r2,0]               add_s   r0,r0,r2
        mpy     r0,r0,0x24              nop_s
        j_s.d   [blink]
        add_s   r0,r0,r2

<page_to_pfn>:
        ld_s    r2,[r0,0]               ld_s    r2,[r0,0]
        lsr_s   r2,r2,0x1f              lsr_s   r2,r2,0x1b
        mpy     r2,r2,1896              add3    r2,0x80529d1c,r2
        add     r3,r2,0x80500668        ld_s    r2,[r2,0]
        add_s   r2,r2,0x8050066c        bmskn   r2,r2,0x3
        ld_s    r3,[r3,0]               sub_s   r0,r0,r2
        sub_s   r0,r0,r3                asr_s   r0,r0,0x2
        ld_s    r2,[r2,0]               mpy     r0,r0,0x38e38e39
        asr_s   r0,r0,0x2               j_s     [blink]
        mpy     r0,r0,0x38e38e39
        j_s.d   [blink]
        add_s   r0,r0,r2
        nop_s

<pfn_valid>:
        cmp_s   r0,0x3ffff              lsr_s   r0,r0,0xe
        mov_s   r2,0                    brhs.nt r0,0x20,24
        mov.ls  r2,0x768                add3    r0,0x80529d1c,r0
        add_s   r2,r2,0x80500814        breq_s  r0,0,12
        ld.as   r3,[r2,-106]            ld_s    r0,[r0,0]
        ld.as   r2,[r2,-104]            j_s.d   [blink]
        add_s   r2,r2,r3                xbfu    r0,r0,0x1
        j_s.d   [blink]                 j_s.d   [blink]
        seths   r0,r2,r0                mov_s   r0,0
        nop_s

Still, SPARSEMEM has an issue with potentially wasted memory allocated for
the memory map. The memory maps are allocated for each present section,
which means that if part of the section is not populated we'll have a bunch
of unused 'struct page' objects. The smaller the section size, the smaller
is memory overhead, but the section size cannot be much smaller than the
physical address because 

        MAX_PHYSMEM_BITS - SECTION_SIZE_BITS

has to fit into page flags and the room there is limited.

There is yet another possibility to support separate banks. It is possible
to use FLATMEM and free the memmap allocated for the hole, like, for
instance, ARM does [1]. This will require ARC's override for pfn_valid()
that takes into account the actual memory configuration rather than relies
on the memmap.

[1] https://elixir.bootlin.com/linux/latest/source/arch/arm/mm/init.c#L305

Mike Rapoport (1):
  arc: add sparsemem support

 arch/arc/Kconfig                 | 10 ++++++++++
 arch/arc/include/asm/sparsemem.h | 13 +++++++++++++
 arch/arc/mm/init.c               |  6 +++++-
 3 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 arch/arc/include/asm/sparsemem.h

-- 
2.26.2

Reply via email to