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 Original line Diff line number Diff line
@@ -355,8 +355,9 @@ config RMW_INSNS
	  adventurous.
	  adventurous.


config SINGLE_MEMORY_CHUNK
config SINGLE_MEMORY_CHUNK
	bool "Use one physical chunk of memory only"
	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
	depends on ADVANCED && !SUN3
	default y if SUN3
	select NEED_MULTIPLE_NODES
	help
	help
	  Ignore all but the first contiguous chunk of physical memory for VM
	  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
	  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
	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
	  this problem.
	  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"
source "mm/Kconfig"


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


static struct mem_info m68k_ramdisk;
struct mem_info m68k_ramdisk;


static char m68k_command_line[CL_SIZE];
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)
void __init setup_arch(char **cmdline_p)
{
{
	extern int _etext, _edata, _end;
	extern int _etext, _edata, _end;
#ifndef CONFIG_SUN3
	unsigned long endmem, startmem;
#endif
	int i;
	int i;


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


#ifndef CONFIG_SUN3
	paging_init();
	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);


#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
#ifdef CONFIG_BLK_DEV_INITRD
	if (m68k_ramdisk.size) {
	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_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
		initrd_end = initrd_start + m68k_ramdisk.size;
		initrd_end = initrd_start + m68k_ramdisk.size;
		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
@@ -362,8 +343,6 @@ void __init setup_arch(char **cmdline_p)


#endif /* !CONFIG_SUN3 */
#endif /* !CONFIG_SUN3 */


	paging_init();

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


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


DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
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
 * ZERO_PAGE is a special page that is used for zero-initialized
 * data and COW.
 * data and COW.
@@ -40,24 +72,27 @@ void *empty_zero_page;


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


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


/* References to section boundaries */
/* References to section boundaries */


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


extern pmd_t *zero_pgtable;
extern pmd_t *zero_pgtable;


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

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


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


	/* this will put all memory onto the freelists */
	/* 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(page))
		if (PageReserved(virt_to_page(tmp))) {
				continue;
			if (tmp >= (unsigned long)&_text
			if (addr >= _text &&
			    && tmp < (unsigned long)&_etext)
			    addr < _etext)
				codepages++;
				codepages++;
			else if (tmp >= (unsigned long) &__init_begin
			else if (addr >= __init_begin &&
				 && tmp < (unsigned long) &__init_end)
				 addr < __init_end)
				initpages++;
				initpages++;
			else
			else
				datapages++;
				datapages++;
			continue;
		}
		}
	}
	}


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


	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
	       (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
	       (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
	       max_mapnr << (PAGE_SHIFT-10),
	       totalram_pages << (PAGE_SHIFT-10),
	       codepages << (PAGE_SHIFT-10),
	       codepages << (PAGE_SHIFT-10),
	       datapages << (PAGE_SHIFT-10),
	       datapages << (PAGE_SHIFT-10),
	       initpages << (PAGE_SHIFT-10));
	       initpages << (PAGE_SHIFT-10));
+0 −73
Original line number Original line Diff line number Diff line
@@ -127,67 +127,6 @@ int free_pointer_table (pmd_t *ptable)
	return 0;
	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 */
/* invalidate page in both caches */
static inline void clear040(unsigned long paddr)
static inline void clear040(unsigned long paddr)
{
{
@@ -354,15 +293,3 @@ void cache_push (unsigned long paddr, int len)
}
}
EXPORT_SYMBOL(cache_push);
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