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

Commit 12d810c1 authored by Roman Zippel's avatar Roman Zippel Committed by Linus Torvalds
Browse files

m68k: discontinuous memory support



Fix support for discontinuous memory

Signed-off-by: default avatarRoman Zippel <zippel@linux-m68k.org>
Signed-off-by: default avatarGeert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 00c541ea
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -355,8 +355,9 @@ config RMW_INSNS
	  adventurous.

config SINGLE_MEMORY_CHUNK
	bool "Use one physical chunk of memory only"
	depends on ADVANCED && !SUN3
	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
	default y if SUN3
	select NEED_MULTIPLE_NODES
	help
	  Ignore all but the first contiguous chunk of physical memory for VM
	  purposes.  This will save a few bytes kernel size and may speed up
@@ -377,6 +378,14 @@ config 060_WRITETHROUGH
	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
	  this problem.

config ARCH_DISCONTIGMEM_ENABLE
	def_bool !SINGLE_MEMORY_CHUNK

config NODES_SHIFT
	int
	default "3"
	depends on !SINGLE_MEMORY_CHUNK

source "mm/Kconfig"

endmenu
+3 −0
Original line number Diff line number Diff line
@@ -149,6 +149,9 @@ void module_fixup(struct module *mod, struct m68k_fixup_info *start,
		case m68k_fixup_memoffset:
			*(u32 *)fixup->addr = m68k_memoffset;
			break;
		case m68k_fixup_vnode_shift:
			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
			break;
		}
	}
}
+8 −29
Original line number Diff line number Diff line
@@ -60,14 +60,12 @@ extern unsigned long availmem;
int m68k_num_memory;
int m68k_realnum_memory;
EXPORT_SYMBOL(m68k_realnum_memory);
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
unsigned long m68k_memoffset;
EXPORT_SYMBOL(m68k_memoffset);
#endif
struct mem_info m68k_memory[NUM_MEMINFO];
EXPORT_SYMBOL(m68k_memory);

static struct mem_info m68k_ramdisk;
struct mem_info m68k_ramdisk;

static char m68k_command_line[CL_SIZE];

@@ -208,9 +206,6 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
void __init setup_arch(char **cmdline_p)
{
	extern int _etext, _edata, _end;
#ifndef CONFIG_SUN3
	unsigned long endmem, startmem;
#endif
	int i;

	/* The bootinfo is located right after the kernel bss */
@@ -320,30 +315,16 @@ void __init setup_arch(char **cmdline_p)
		panic("No configuration setup");
	}

#ifndef CONFIG_SUN3
	startmem= m68k_memory[0].addr;
	endmem = startmem + m68k_memory[0].size;
	high_memory = (void *)PAGE_OFFSET;
	for (i = 0; i < m68k_num_memory; i++) {
		m68k_memory[i].size &= MASK_256K;
		if (m68k_memory[i].addr < startmem)
			startmem = m68k_memory[i].addr;
		if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
			endmem = m68k_memory[i].addr+m68k_memory[i].size;
		high_memory += m68k_memory[i].size;
	}

	availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
				      startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);

	for (i = 0; i < m68k_num_memory; i++)
		free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);

	reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
	paging_init();

#ifndef CONFIG_SUN3
	for (i = 1; i < m68k_num_memory; i++)
		free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
				  m68k_memory[i].size);
#ifdef CONFIG_BLK_DEV_INITRD
	if (m68k_ramdisk.size) {
		reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
		reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
				     m68k_ramdisk.addr, m68k_ramdisk.size);
		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
		initrd_end = initrd_start + m68k_ramdisk.size;
		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
@@ -362,8 +343,6 @@ void __init setup_arch(char **cmdline_p)

#endif /* !CONFIG_SUN3 */

	paging_init();

/* set ISA defs early as possible */
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
#if defined(CONFIG_Q40)
+78 −41
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 *  to motorola.c and sun3mmu.c
 */

#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -31,6 +32,37 @@

DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);

static bootmem_data_t __initdata bootmem_data[MAX_NUMNODES];

pg_data_t pg_data_map[MAX_NUMNODES];
EXPORT_SYMBOL(pg_data_map);

int m68k_virt_to_node_shift;

#ifndef CONFIG_SINGLE_MEMORY_CHUNK
pg_data_t *pg_data_table[65];
EXPORT_SYMBOL(pg_data_table);
#endif

void m68k_setup_node(int node)
{
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
	struct mem_info *info = m68k_memory + node;
	int i, end;

	i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
	end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
	for (; i <= end; i++) {
		if (pg_data_table[i])
			printk("overlap at %u for chunk %u\n", i, node);
		pg_data_table[i] = pg_data_map + node;
	}
#endif
	pg_data_map[node].bdata = bootmem_data + node;
	node_set_online(node);
}


/*
 * ZERO_PAGE is a special page that is used for zero-initialized
 * data and COW.
@@ -40,24 +72,27 @@ void *empty_zero_page;

void show_mem(void)
{
    unsigned long i;
	pg_data_t *pgdat;
	int free = 0, total = 0, reserved = 0, shared = 0;
	int cached = 0;
	int i;

	printk("\nMem-info:\n");
	show_free_areas();
	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
    i = max_mapnr;
    while (i-- > 0) {
	for_each_online_pgdat(pgdat) {
		for (i = 0; i < pgdat->node_spanned_pages; i++) {
			struct page *page = pgdat->node_mem_map + i;
			total++;
	if (PageReserved(mem_map+i))
			if (PageReserved(page))
				reserved++;
	else if (PageSwapCache(mem_map+i))
			else if (PageSwapCache(page))
				cached++;
	else if (!page_count(mem_map+i))
			else if (!page_count(page))
				free++;
			else
	    shared += page_count(mem_map+i) - 1;
				shared += page_count(page) - 1;
		}
	}
	printk("%d pages of RAM\n",total);
	printk("%d free pages\n",free);
@@ -70,22 +105,18 @@ extern void init_pointer_table(unsigned long ptable);

/* References to section boundaries */

extern char _text, _etext, _edata, __bss_start, _end;
extern char __init_begin, __init_end;
extern char _text[], _etext[];
extern char __init_begin[], __init_end[];

extern pmd_t *zero_pgtable;

void __init mem_init(void)
{
	pg_data_t *pgdat;
	int codepages = 0;
	int datapages = 0;
	int initpages = 0;
	unsigned long tmp;
#ifndef CONFIG_SUN3
	int i;
#endif

	max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT);

#ifdef CONFIG_ATARI
	if (MACH_IS_ATARI)
@@ -93,19 +124,25 @@ void __init mem_init(void)
#endif

	/* this will put all memory onto the freelists */
	totalram_pages = free_all_bootmem();
	totalram_pages = num_physpages = 0;
	for_each_online_pgdat(pgdat) {
		num_physpages += pgdat->node_present_pages;

		totalram_pages += free_all_bootmem_node(pgdat);
		for (i = 0; i < pgdat->node_spanned_pages; i++) {
			struct page *page = pgdat->node_mem_map + i;
			char *addr = page_to_virt(page);

	for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) {
		if (PageReserved(virt_to_page(tmp))) {
			if (tmp >= (unsigned long)&_text
			    && tmp < (unsigned long)&_etext)
			if (!PageReserved(page))
				continue;
			if (addr >= _text &&
			    addr < _etext)
				codepages++;
			else if (tmp >= (unsigned long) &__init_begin
				 && tmp < (unsigned long) &__init_end)
			else if (addr >= __init_begin &&
				 addr < __init_end)
				initpages++;
			else
				datapages++;
			continue;
		}
	}

@@ -124,7 +161,7 @@ void __init mem_init(void)

	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
	       (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
	       max_mapnr << (PAGE_SHIFT-10),
	       totalram_pages << (PAGE_SHIFT-10),
	       codepages << (PAGE_SHIFT-10),
	       datapages << (PAGE_SHIFT-10),
	       initpages << (PAGE_SHIFT-10));
+0 −73
Original line number Diff line number Diff line
@@ -127,67 +127,6 @@ int free_pointer_table (pmd_t *ptable)
	return 0;
}

#ifdef DEBUG_INVALID_PTOV
int mm_inv_cnt = 5;
#endif

#ifndef CONFIG_SINGLE_MEMORY_CHUNK
/*
 * The following two routines map from a physical address to a kernel
 * virtual address and vice versa.
 */
unsigned long mm_vtop(unsigned long vaddr)
{
	int i=0;
	unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET;

	do {
		if (voff < m68k_memory[i].size) {
#ifdef DEBUGPV
			printk ("VTOP(%p)=%lx\n", vaddr,
				m68k_memory[i].addr + voff);
#endif
			return m68k_memory[i].addr + voff;
		}
		voff -= m68k_memory[i].size;
	} while (++i < m68k_num_memory);

	/* As a special case allow `__pa(high_memory)'.  */
	if (voff == 0)
		return m68k_memory[i-1].addr + m68k_memory[i-1].size;

	return -1;
}
EXPORT_SYMBOL(mm_vtop);

unsigned long mm_ptov (unsigned long paddr)
{
	int i = 0;
	unsigned long poff, voff = PAGE_OFFSET;

	do {
		poff = paddr - m68k_memory[i].addr;
		if (poff < m68k_memory[i].size) {
#ifdef DEBUGPV
			printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
#endif
			return poff + voff;
		}
		voff += m68k_memory[i].size;
	} while (++i < m68k_num_memory);

#ifdef DEBUG_INVALID_PTOV
	if (mm_inv_cnt > 0) {
		mm_inv_cnt--;
		printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n",
			paddr, __builtin_return_address(0));
	}
#endif
	return -1;
}
EXPORT_SYMBOL(mm_ptov);
#endif

/* invalidate page in both caches */
static inline void clear040(unsigned long paddr)
{
@@ -354,15 +293,3 @@ void cache_push (unsigned long paddr, int len)
}
EXPORT_SYMBOL(cache_push);
#ifndef CONFIG_SINGLE_MEMORY_CHUNK
int mm_end_of_chunk (unsigned long addr, int len)
{
	int i;

	for (i = 0; i < m68k_num_memory; i++)
		if (m68k_memory[i].addr + m68k_memory[i].size == addr + len)
			return 1;
	return 0;
}
EXPORT_SYMBOL(mm_end_of_chunk);
#endif
Loading