m68k: discontinuous memory support
Fix support for discontinuous memory Signed-off-by: Roman Zippel <zippel@linux-m68k.org> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
00c541eae7
Коммит
12d810c1b8
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
paging_init();
|
||||
|
||||
#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);
|
||||
|
||||
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)
|
||||
|
|
|
@ -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,52 +72,51 @@ void *empty_zero_page;
|
|||
|
||||
void show_mem(void)
|
||||
{
|
||||
unsigned long i;
|
||||
int free = 0, total = 0, reserved = 0, shared = 0;
|
||||
int cached = 0;
|
||||
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) {
|
||||
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);
|
||||
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)
|
||||
|
@ -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;
|
||||
|
||||
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 += 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -43,6 +43,11 @@ unsigned long mm_cachebits;
|
|||
EXPORT_SYMBOL(mm_cachebits);
|
||||
#endif
|
||||
|
||||
/* size of memory already mapped in head.S */
|
||||
#define INIT_MAPPED_SIZE (4UL<<20)
|
||||
|
||||
extern unsigned long availmem;
|
||||
|
||||
static pte_t * __init kernel_page_table(void)
|
||||
{
|
||||
pte_t *ptablep;
|
||||
|
@ -98,19 +103,20 @@ static pmd_t * __init kernel_ptr_table(void)
|
|||
return last_pgtable;
|
||||
}
|
||||
|
||||
static unsigned long __init
|
||||
map_chunk (unsigned long addr, long size)
|
||||
static void __init map_node(int node)
|
||||
{
|
||||
#define PTRTREESIZE (256*1024)
|
||||
#define ROOTTREESIZE (32*1024*1024)
|
||||
static unsigned long virtaddr = PAGE_OFFSET;
|
||||
unsigned long physaddr;
|
||||
unsigned long physaddr, virtaddr, size;
|
||||
pgd_t *pgd_dir;
|
||||
pmd_t *pmd_dir;
|
||||
pte_t *pte_dir;
|
||||
|
||||
physaddr = (addr | m68k_supervisor_cachemode |
|
||||
_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
|
||||
size = m68k_memory[node].size;
|
||||
physaddr = m68k_memory[node].addr;
|
||||
virtaddr = (unsigned long)phys_to_virt(physaddr);
|
||||
physaddr |= m68k_supervisor_cachemode |
|
||||
_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY;
|
||||
if (CPU_IS_040_OR_060)
|
||||
physaddr |= _PAGE_GLOBAL040;
|
||||
|
||||
|
@ -190,8 +196,6 @@ map_chunk (unsigned long addr, long size)
|
|||
#ifdef DEBUG
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
return virtaddr;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -200,15 +204,16 @@ map_chunk (unsigned long addr, long size)
|
|||
*/
|
||||
void __init paging_init(void)
|
||||
{
|
||||
int chunk;
|
||||
unsigned long mem_avail = 0;
|
||||
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
|
||||
unsigned long min_addr, max_addr;
|
||||
unsigned long addr, size, end;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
extern unsigned long availmem;
|
||||
printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
|
||||
kernel_pg_dir, availmem, start_mem, end_mem);
|
||||
printk ("start of paging_init (%p, %lx)\n",
|
||||
kernel_pg_dir, availmem);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -222,27 +227,62 @@ void __init paging_init(void)
|
|||
pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
|
||||
}
|
||||
|
||||
min_addr = m68k_memory[0].addr;
|
||||
max_addr = min_addr + m68k_memory[0].size;
|
||||
for (i = 1; i < m68k_num_memory;) {
|
||||
if (m68k_memory[i].addr < min_addr) {
|
||||
printk("Ignoring memory chunk at 0x%lx:0x%lx before the first chunk\n",
|
||||
m68k_memory[i].addr, m68k_memory[i].size);
|
||||
printk("Fix your bootloader or use a memfile to make use of this area!\n");
|
||||
m68k_num_memory--;
|
||||
memmove(m68k_memory + i, m68k_memory + i + 1,
|
||||
(m68k_num_memory - i) * sizeof(struct mem_info));
|
||||
continue;
|
||||
}
|
||||
addr = m68k_memory[i].addr + m68k_memory[i].size;
|
||||
if (addr > max_addr)
|
||||
max_addr = addr;
|
||||
i++;
|
||||
}
|
||||
m68k_memoffset = min_addr - PAGE_OFFSET;
|
||||
m68k_virt_to_node_shift = fls(max_addr - min_addr - 1) - 6;
|
||||
|
||||
module_fixup(NULL, __start_fixup, __stop_fixup);
|
||||
flush_icache();
|
||||
|
||||
/*
|
||||
* Map the physical memory available into the kernel virtual
|
||||
* address space. It may allocate some memory for page
|
||||
* tables and thus modify availmem.
|
||||
*/
|
||||
high_memory = phys_to_virt(max_addr);
|
||||
|
||||
for (chunk = 0; chunk < m68k_num_memory; chunk++) {
|
||||
mem_avail = map_chunk (m68k_memory[chunk].addr,
|
||||
m68k_memory[chunk].size);
|
||||
min_low_pfn = availmem >> PAGE_SHIFT;
|
||||
max_low_pfn = max_addr >> PAGE_SHIFT;
|
||||
|
||||
for (i = 0; i < m68k_num_memory; i++) {
|
||||
addr = m68k_memory[i].addr;
|
||||
end = addr + m68k_memory[i].size;
|
||||
m68k_setup_node(i);
|
||||
availmem = PAGE_ALIGN(availmem);
|
||||
availmem += init_bootmem_node(NODE_DATA(i),
|
||||
availmem >> PAGE_SHIFT,
|
||||
addr >> PAGE_SHIFT,
|
||||
end >> PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the physical memory available into the kernel virtual
|
||||
* address space. First initialize the bootmem allocator with
|
||||
* the memory we already mapped, so map_node() has something
|
||||
* to allocate.
|
||||
*/
|
||||
addr = m68k_memory[0].addr;
|
||||
size = m68k_memory[0].size;
|
||||
free_bootmem_node(NODE_DATA(0), availmem, min(INIT_MAPPED_SIZE, size) - (availmem - addr));
|
||||
map_node(0);
|
||||
if (size > INIT_MAPPED_SIZE)
|
||||
free_bootmem_node(NODE_DATA(0), addr + INIT_MAPPED_SIZE, size - INIT_MAPPED_SIZE);
|
||||
|
||||
for (i = 1; i < m68k_num_memory; i++)
|
||||
map_node(i);
|
||||
|
||||
flush_tlb_all();
|
||||
#ifdef DEBUG
|
||||
printk ("memory available is %ldKB\n", mem_avail >> 10);
|
||||
printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
|
||||
start_mem, end_mem);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* initialize the bad page table and bad page to point
|
||||
|
@ -259,14 +299,11 @@ void __init paging_init(void)
|
|||
#ifdef DEBUG
|
||||
printk ("before free_area_init\n");
|
||||
#endif
|
||||
zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
|
||||
(mach_max_dma_address+1) : (unsigned long)high_memory);
|
||||
zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
|
||||
|
||||
zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
|
||||
zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
|
||||
|
||||
free_area_init(zones_size);
|
||||
for (i = 0; i < m68k_num_memory; i++) {
|
||||
zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
|
||||
free_area_init_node(i, pg_data_map + i, zones_size,
|
||||
m68k_memory[i].addr >> PAGE_SHIFT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
extern char __init_begin, __init_end;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <asm/contregs.h>
|
||||
#include <asm/movs.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/sun3-head.h>
|
||||
#include <asm/sun3mmu.h>
|
||||
#include <asm/rtc.h>
|
||||
|
@ -127,6 +128,7 @@ void __init sun3_bootmem_alloc(unsigned long memory_start, unsigned long memory_
|
|||
high_memory = (void *)memory_end;
|
||||
availmem = memory_start;
|
||||
|
||||
m68k_setup_node(0);
|
||||
availmem += init_bootmem_node(NODE_DATA(0), start_page, 0, num_pages);
|
||||
availmem = (availmem + (PAGE_SIZE-1)) & PAGE_MASK;
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef _ASM_M68K_MMZONE_H_
|
||||
#define _ASM_M68K_MMZONE_H_
|
||||
|
||||
extern pg_data_t pg_data_map[];
|
||||
|
||||
#define NODE_DATA(nid) (&pg_data_map[nid])
|
||||
#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map)
|
||||
|
||||
#endif /* _ASM_M68K_MMZONE_H_ */
|
|
@ -17,6 +17,7 @@ struct mod_arch_specific {
|
|||
|
||||
enum m68k_fixup_type {
|
||||
m68k_fixup_memoffset,
|
||||
m68k_fixup_vnode_shift,
|
||||
};
|
||||
|
||||
struct m68k_fixup_info {
|
||||
|
|
|
@ -130,7 +130,7 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
|
|||
#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
|
||||
#define pte_clear(mm,addr,ptep) ({ pte_val(*(ptep)) = 0; })
|
||||
|
||||
#define pte_page(pte) (mem_map + ((unsigned long)(__va(pte_val(pte)) - PAGE_OFFSET) >> PAGE_SHIFT))
|
||||
#define pte_page(pte) virt_to_page(__va(pte_val(pte)))
|
||||
#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
|
||||
#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
|
||||
|
||||
|
@ -143,7 +143,7 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
|
|||
while (--__i >= 0) \
|
||||
*__ptr++ = 0; \
|
||||
})
|
||||
#define pmd_page(pmd) (mem_map + ((unsigned long)(__va(pmd_val(pmd)) - PAGE_OFFSET) >> PAGE_SHIFT))
|
||||
#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
|
||||
|
||||
|
||||
#define pgd_none(pgd) (!pgd_val(pgd))
|
||||
|
@ -223,10 +223,10 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmdp, unsigned long address)
|
|||
return (pte_t *)__pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
|
||||
}
|
||||
|
||||
#define pte_offset_map(pmdp,address) ((pte_t *)kmap(pmd_page(*pmdp)) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
|
||||
#define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
|
||||
#define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address)
|
||||
#define pte_unmap(pte) kunmap(pte)
|
||||
#define pte_unmap_nested(pte) kunmap(pte)
|
||||
#define pte_unmap(pte) ((void)0)
|
||||
#define pte_unmap_nested(pte) ((void)0)
|
||||
|
||||
/*
|
||||
* Allocate and free page tables. The xxx_kernel() versions are
|
||||
|
|
|
@ -121,7 +121,6 @@ extern unsigned long m68k_memoffset;
|
|||
#ifndef CONFIG_SUN3
|
||||
|
||||
#define WANT_PAGE_VIRTUAL
|
||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
|
||||
static inline unsigned long ___pa(void *vaddr)
|
||||
{
|
||||
|
@ -133,7 +132,7 @@ static inline unsigned long ___pa(void *vaddr)
|
|||
: "0" (vaddr), "i" (m68k_fixup_memoffset));
|
||||
return paddr;
|
||||
}
|
||||
#define __pa(vaddr) ___pa((void *)(vaddr))
|
||||
#define __pa(vaddr) ___pa((void *)(vaddr))
|
||||
static inline void *__va(unsigned long paddr)
|
||||
{
|
||||
void *vaddr;
|
||||
|
@ -145,11 +144,6 @@ static inline void *__va(unsigned long paddr)
|
|||
return vaddr;
|
||||
}
|
||||
|
||||
#else
|
||||
#define __pa(vaddr) virt_to_phys((void *)(vaddr))
|
||||
#define __va(paddr) phys_to_virt((unsigned long)(paddr))
|
||||
#endif
|
||||
|
||||
#else /* !CONFIG_SUN3 */
|
||||
/* This #define is a horrible hack to suppress lots of warnings. --m */
|
||||
#define __pa(x) ___pa((unsigned long)(x))
|
||||
|
@ -184,11 +178,47 @@ static inline void *__va(unsigned long x)
|
|||
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
|
||||
#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
|
||||
|
||||
#define virt_to_page(kaddr) (mem_map + (((unsigned long)(kaddr)-PAGE_OFFSET) >> PAGE_SHIFT))
|
||||
#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
|
||||
extern int m68k_virt_to_node_shift;
|
||||
|
||||
#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
|
||||
#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
|
||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
#define __virt_to_node(addr) (&pg_data_map[0])
|
||||
#else
|
||||
extern struct pglist_data *pg_data_table[];
|
||||
|
||||
static inline __attribute_const__ int __virt_to_node_shift(void)
|
||||
{
|
||||
int shift;
|
||||
|
||||
asm (
|
||||
"1: moveq #0,%0\n"
|
||||
m68k_fixup(%c1, 1b)
|
||||
: "=d" (shift)
|
||||
: "i" (m68k_fixup_vnode_shift));
|
||||
return shift;
|
||||
}
|
||||
|
||||
#define __virt_to_node(addr) (pg_data_table[(unsigned long)(addr) >> __virt_to_node_shift()])
|
||||
#endif
|
||||
|
||||
#define virt_to_page(addr) ({ \
|
||||
pfn_to_page(virt_to_pfn(addr)); \
|
||||
})
|
||||
#define page_to_virt(page) ({ \
|
||||
pfn_to_virt(page_to_pfn(page)); \
|
||||
})
|
||||
|
||||
#define pfn_to_page(pfn) ({ \
|
||||
unsigned long __pfn = (pfn); \
|
||||
struct pglist_data *pgdat; \
|
||||
pgdat = __virt_to_node((unsigned long)pfn_to_virt(__pfn)); \
|
||||
pgdat->node_mem_map + (__pfn - pgdat->node_start_pfn); \
|
||||
})
|
||||
#define page_to_pfn(_page) ({ \
|
||||
struct page *__p = (_page); \
|
||||
struct pglist_data *pgdat; \
|
||||
pgdat = &pg_data_map[page_to_nid(__p)]; \
|
||||
((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn; \
|
||||
})
|
||||
|
||||
#define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
|
||||
#define pfn_valid(pfn) virt_addr_valid(pfn_to_virt(pfn))
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
#include <asm/virtconvert.h>
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_SUN3
|
||||
#include <asm/sun3_pgalloc.h>
|
||||
#else
|
||||
#include <asm/motorola_pgalloc.h>
|
||||
#endif
|
||||
|
||||
extern void m68k_setup_node(int node);
|
||||
|
||||
#endif /* M68K_PGALLOC_H */
|
||||
|
|
|
@ -107,22 +107,7 @@ extern void *empty_zero_page;
|
|||
/* 64-bit machines, beware! SRB. */
|
||||
#define SIZEOF_PTR_LOG2 2
|
||||
|
||||
/*
|
||||
* Check if the addr/len goes up to the end of a physical
|
||||
* memory chunk. Used for DMA functions.
|
||||
*/
|
||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
/*
|
||||
* It makes no sense to consider whether we cross a memory boundary if
|
||||
* we support just one physical chunk of memory.
|
||||
*/
|
||||
static inline int mm_end_of_chunk(unsigned long addr, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int mm_end_of_chunk (unsigned long addr, int len);
|
||||
#endif
|
||||
#define mm_end_of_chunk(addr, len) 0
|
||||
|
||||
extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
|
||||
|
||||
|
|
|
@ -132,8 +132,8 @@ static inline void pte_clear (struct mm_struct *mm, unsigned long addr, pte_t *p
|
|||
#define pfn_pte(pfn, pgprot) \
|
||||
({ pte_t __pte; pte_val(__pte) = pfn | pgprot_val(pgprot); __pte; })
|
||||
|
||||
#define pte_page(pte) (mem_map+((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT))
|
||||
#define pmd_page(pmd) (mem_map+((__pmd_page(pmd) - PAGE_OFFSET) >> PAGE_SHIFT))
|
||||
#define pte_page(pte) virt_to_page(__pte_page(pte))
|
||||
#define pmd_page(pmd) virt_to_page(__pmd_page(pmd))
|
||||
|
||||
|
||||
static inline int pmd_none2 (pmd_t *pmd) { return !pmd_val (*pmd); }
|
||||
|
|
|
@ -8,56 +8,35 @@
|
|||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/mmzone.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
#ifdef CONFIG_AMIGA
|
||||
#include <asm/amigahw.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Change virtual addresses to physical addresses and vv.
|
||||
*/
|
||||
#ifndef CONFIG_SUN3
|
||||
extern unsigned long mm_vtop(unsigned long addr) __attribute_const__;
|
||||
extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
|
||||
#else
|
||||
static inline unsigned long mm_vtop(unsigned long vaddr)
|
||||
{
|
||||
return __pa(vaddr);
|
||||
}
|
||||
|
||||
static inline unsigned long mm_ptov(unsigned long paddr)
|
||||
{
|
||||
return (unsigned long)__va(paddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
static inline unsigned long virt_to_phys(void *vaddr)
|
||||
{
|
||||
return (unsigned long)vaddr - PAGE_OFFSET + m68k_memory[0].addr;
|
||||
}
|
||||
|
||||
static inline void * phys_to_virt(unsigned long paddr)
|
||||
{
|
||||
return (void *)(paddr - m68k_memory[0].addr + PAGE_OFFSET);
|
||||
}
|
||||
#else
|
||||
static inline unsigned long virt_to_phys(void *address)
|
||||
{
|
||||
return mm_vtop((unsigned long)address);
|
||||
return __pa(address);
|
||||
}
|
||||
|
||||
static inline void *phys_to_virt(unsigned long address)
|
||||
{
|
||||
return (void *) mm_ptov(address);
|
||||
return __va(address);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Permanent address of a page. */
|
||||
#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
|
||||
#define page_to_phys(page) virt_to_phys((void *)__page_address(page))
|
||||
#ifdef CONFIG_SINGLE_MEMORY_CHUNK
|
||||
#define page_to_phys(page) \
|
||||
__pa(PAGE_OFFSET + (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
|
||||
#else
|
||||
#define page_to_phys(_page) ({ \
|
||||
struct page *__page = _page; \
|
||||
struct pglist_data *pgdat; \
|
||||
pgdat = pg_data_table[page_to_nid(__page)]; \
|
||||
page_to_pfn(__page) << PAGE_SHIFT; \
|
||||
})
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IO bus memory addresses are 1:1 with the physical address,
|
||||
|
|
|
@ -2689,7 +2689,7 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
|
|||
map = alloc_bootmem_node(pgdat, size);
|
||||
pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
|
||||
}
|
||||
#ifdef CONFIG_FLATMEM
|
||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||
/*
|
||||
* With no DISCONTIG, the global mem_map is just set as node 0's
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче