Skip to content

Commit

Permalink
m68k: discontinuous memory support
Browse files Browse the repository at this point in the history
Fix support for discontinuous memory

Signed-off-by: Roman Zippel <[email protected]>
Signed-off-by: Geert Uytterhoeven <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Roman Zippel authored and Linus Torvalds committed May 31, 2007
1 parent 00c541e commit 12d810c
Show file tree
Hide file tree
Showing 16 changed files with 247 additions and 248 deletions.
13 changes: 11 additions & 2 deletions arch/m68k/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions arch/m68k/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
37 changes: 8 additions & 29 deletions arch/m68k/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down
119 changes: 78 additions & 41 deletions arch/m68k/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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.
Expand All @@ -40,72 +72,77 @@ void *empty_zero_page;

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

printk("\nMem-info:\n");
show_free_areas();
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
i = max_mapnr;
while (i-- > 0) {
total++;
if (PageReserved(mem_map+i))
reserved++;
else if (PageSwapCache(mem_map+i))
cached++;
else if (!page_count(mem_map+i))
free++;
else
shared += page_count(mem_map+i) - 1;
}
printk("%d pages of RAM\n",total);
printk("%d free pages\n",free);
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
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));
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(page))
reserved++;
else if (PageSwapCache(page))
cached++;
else if (!page_count(page))
free++;
else
shared += page_count(page) - 1;
}
}
printk("%d pages of RAM\n",total);
printk("%d free pages\n",free);
printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached);
}

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)
atari_stram_mem_init_hook();
#endif

/* this will put all memory onto the freelists */
totalram_pages = free_all_bootmem();

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)
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);

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;
}
}

Expand All @@ -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));
Expand Down
73 changes: 0 additions & 73 deletions arch/m68k/mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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

0 comments on commit 12d810c

Please sign in to comment.