Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45890f6d authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARC: mm: HIGHMEM: kmap API implementation



Implement kmap* API for ARC.

This enables
 - permanent kernel maps (pkmaps): :kmap() API
 - fixmap : kmap_atomic()

We use a very simple/uniform approach for both (unlike some of the other
arches). So fixmap doesn't use the customary compile time address stuff.
The important semantic is sleep'ability (pkmap) vs. not (fixmap) which
the API guarantees.

Note that this patch only enables highmem for subsequent PAE40 support
as there is no real highmem for ARC in pure 32-bit paradigm as explained
below.

ARC has 2:2 address split of the 32-bit address space with lower half
being translated (virtual) while upper half unstranslated
(0x8000_0000 to 0xFFFF_FFFF). kernel itself is linked at base of
unstranslated space (i.e. 0x8000_0000 onwards), which is mapped to say
DDR 0x0 by external Bus Glue logic (outside the core). So kernel can
potentially access 1.75G worth of memory directly w/o need for highmem.
(the top 256M is taken by uncached peripheral space from 0xF000_0000 to
0xFFFF_FFFF)

In PAE40, hardware can address memory beyond 4G (0x1_0000_0000) while
the logical/virtual addresses remain 32-bits. Thus highmem is required
for kernel proper to be able to access these pages for it's own purposes
(user space is agnostic to this anyways).

Signed-off-by: default avatarAlexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent 6101be5a
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -446,6 +446,13 @@ config LINUX_LINK_BASE
	  Linux needs to be scooted a bit.
	  If you don't know what the above means, leave this setting alone.

config HIGHMEM
	bool "High Memory Support"
	help
	  With ARC 2G:2G address split, only upper 2G is directly addressable by
	  kernel. Enable this to potentially allow access to rest of 2G and PAE
	  in future

config ARC_CURR_IN_REG
	bool "Dedicate Register r25 for current_task pointer"
	default y
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#ifndef _ASM_HIGHMEM_H
#define _ASM_HIGHMEM_H

#ifdef CONFIG_HIGHMEM

#include <uapi/asm/page.h>
#include <asm/kmap_types.h>

/* start after vmalloc area */
#define FIXMAP_BASE		(PAGE_OFFSET - FIXMAP_SIZE - PKMAP_SIZE)
#define FIXMAP_SIZE		PGDIR_SIZE	/* only 1 PGD worth */
#define KM_TYPE_NR		((FIXMAP_SIZE >> PAGE_SHIFT)/NR_CPUS)
#define FIXMAP_ADDR(nr)		(FIXMAP_BASE + ((nr) << PAGE_SHIFT))

/* start after fixmap area */
#define PKMAP_BASE		(FIXMAP_BASE + FIXMAP_SIZE)
#define PKMAP_SIZE		PGDIR_SIZE
#define LAST_PKMAP		(PKMAP_SIZE >> PAGE_SHIFT)
#define LAST_PKMAP_MASK		(LAST_PKMAP - 1)
#define PKMAP_ADDR(nr)		(PKMAP_BASE + ((nr) << PAGE_SHIFT))
#define PKMAP_NR(virt)		(((virt) - PKMAP_BASE) >> PAGE_SHIFT)

#define kmap_prot		PAGE_KERNEL


#include <asm/cacheflush.h>

extern void *kmap(struct page *page);
extern void *kmap_high(struct page *page);
extern void *kmap_atomic(struct page *page);
extern void __kunmap_atomic(void *kvaddr);
extern void kunmap_high(struct page *page);

extern void kmap_init(void);

static inline void flush_cache_kmaps(void)
{
	flush_cache_all();
}

static inline void kunmap(struct page *page)
{
	BUG_ON(in_interrupt());
	if (!PageHighMem(page))
		return;
	kunmap_high(page);
}


#endif

#endif
+18 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#ifndef _ASM_KMAP_TYPES_H
#define _ASM_KMAP_TYPES_H

/*
 * We primarily need to define KM_TYPE_NR here but that in turn
 * is a function of PGDIR_SIZE etc.
 * To avoid circular deps issue, put everything in asm/highmem.h
 */
#endif
+6 −1
Original line number Diff line number Diff line
@@ -114,7 +114,12 @@ extern unsigned int get_wchan(struct task_struct *p);
 * -----------------------------------------------------------------------------
 */
#define VMALLOC_START	0x70000000
#define VMALLOC_SIZE	(PAGE_OFFSET - VMALLOC_START)

/*
 * 1 PGDIR_SIZE each for fixmap/pkmap, 2 PGDIR_SIZE gutter
 * See asm/highmem.h for details
 */
#define VMALLOC_SIZE	(PAGE_OFFSET - VMALLOC_START - PGDIR_SIZE * 4)
#define VMALLOC_END	(VMALLOC_START + VMALLOC_SIZE)

#define USER_KERNEL_GUTTER    0x10000000
+1 −0
Original line number Diff line number Diff line
@@ -8,3 +8,4 @@

obj-y	:= extable.o ioremap.o dma.o fault.o init.o
obj-y	+= tlb.o tlbex.o cache.o mmap.o
obj-$(CONFIG_HIGHMEM)	+= highmem.o
Loading