init.c 5.61 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 *  arch/s390/mm/init.c
 *
 *  S390 version
 *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *    Author(s): Hartmut Penner (hp@de.ibm.com)
 *
 *  Derived from "arch/i386/mm/init.c"
 *    Copyright (C) 1995  Linus Torvalds
 */

#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/bootmem.h>
26
#include <linux/pfn.h>
27
#include <linux/poison.h>
28
#include <linux/initrd.h>
Linus Torvalds's avatar
Linus Torvalds committed
29 30 31 32 33 34 35 36 37
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/dma.h>
#include <asm/lowcore.h>
#include <asm/tlb.h>
#include <asm/tlbflush.h>
38
#include <asm/sections.h>
Linus Torvalds's avatar
Linus Torvalds committed
39 40 41 42 43 44 45 46

DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);

pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));

void show_mem(void)
{
47 48
	int i, total = 0, reserved = 0;
	int shared = 0, cached = 0;
49
	struct page *page;
Linus Torvalds's avatar
Linus Torvalds committed
50

51 52 53 54 55
	printk("Mem-info:\n");
	show_free_areas();
	printk("Free swap:       %6ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
	i = max_mapnr;
	while (i-- > 0) {
56 57
		if (!pfn_valid(i))
			continue;
58
		page = pfn_to_page(i);
59
		total++;
60
		if (PageReserved(page))
61
			reserved++;
62
		else if (PageSwapCache(page))
63
			cached++;
64 65
		else if (page_count(page))
			shared += page_count(page) - 1;
66 67 68 69 70 71 72 73 74 75 76 77 78
	}
	printk("%d pages of RAM\n", total);
	printk("%d reserved pages\n", reserved);
	printk("%d pages shared\n", shared);
	printk("%d pages swap cached\n", cached);

	printk("%lu pages dirty\n", global_page_state(NR_FILE_DIRTY));
	printk("%lu pages writeback\n", global_page_state(NR_WRITEBACK));
	printk("%lu pages mapped\n", global_page_state(NR_FILE_MAPPED));
	printk("%lu pages slab\n",
	       global_page_state(NR_SLAB_RECLAIMABLE) +
	       global_page_state(NR_SLAB_UNRECLAIMABLE));
	printk("%lu pages pagetables\n", global_page_state(NR_PAGETABLE));
Linus Torvalds's avatar
Linus Torvalds committed
79 80
}

81 82 83 84 85 86 87 88
static void __init setup_ro_region(void)
{
	pgd_t *pgd;
	pmd_t *pmd;
	pte_t *pte;
	pte_t new_pte;
	unsigned long address, end;

89 90
	address = ((unsigned long)&_stext) & PAGE_MASK;
	end = PFN_ALIGN((unsigned long)&_eshared);
91 92 93 94 95 96

	for (; address < end; address += PAGE_SIZE) {
		pgd = pgd_offset_k(address);
		pmd = pmd_offset(pgd, address);
		pte = pte_offset_kernel(pmd, address);
		new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
Gerald Schaefer's avatar
Gerald Schaefer committed
97
		*pte = new_pte;
98 99 100
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
101 102 103 104 105
/*
 * paging_init() sets up the page tables
 */
void __init paging_init(void)
{
106
	static const int ssm_mask = 0x04000000L;
107
	unsigned long max_zone_pfns[MAX_NR_ZONES];
108
	unsigned long pgd_type;
109

110 111
	init_mm.pgd = swapper_pg_dir;
	S390_lowcore.kernel_asce = __pa(init_mm.pgd) & PAGE_MASK;
112
#ifdef CONFIG_64BIT
113 114
	S390_lowcore.kernel_asce |= _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
	pgd_type = _REGION3_ENTRY_EMPTY;
115
#else
116 117
	S390_lowcore.kernel_asce |= _ASCE_TABLE_LENGTH;
	pgd_type = _SEGMENT_ENTRY_EMPTY;
118
#endif
119 120
	clear_table((unsigned long *) init_mm.pgd, pgd_type,
		    sizeof(unsigned long)*2048);
121 122
	vmem_map_init();
	setup_ro_region();
Linus Torvalds's avatar
Linus Torvalds committed
123 124

        /* enable virtual mapping in kernel mode */
125 126 127
	__ctl_load(S390_lowcore.kernel_asce, 1, 1);
	__ctl_load(S390_lowcore.kernel_asce, 7, 7);
	__ctl_load(S390_lowcore.kernel_asce, 13, 13);
128
	__raw_local_irq_ssm(ssm_mask);
Linus Torvalds's avatar
Linus Torvalds committed
129

130
	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
131
#ifdef CONFIG_ZONE_DMA
132
	max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
133
#endif
134 135
	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
	free_area_init_nodes(max_zone_pfns);
Linus Torvalds's avatar
Linus Torvalds committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
}

void __init mem_init(void)
{
	unsigned long codesize, reservedpages, datasize, initsize;

        max_mapnr = num_physpages = max_low_pfn;
        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);

        /* clear the zero-page */
        memset(empty_zero_page, 0, PAGE_SIZE);

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

	reservedpages = 0;

	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
        printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
                max_mapnr << (PAGE_SHIFT-10),
                codesize >> 10,
                reservedpages << (PAGE_SHIFT-10),
                datasize >>10,
                initsize >> 10);
163
	printk("Write protected kernel read-only data: %#lx - %#lx\n",
164 165
	       (unsigned long)&_stext,
	       PFN_ALIGN((unsigned long)&_eshared) - 1);
Linus Torvalds's avatar
Linus Torvalds committed
166 167 168 169 170 171 172 173 174
}

void free_initmem(void)
{
        unsigned long addr;

        addr = (unsigned long)(&__init_begin);
        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
		ClearPageReserved(virt_to_page(addr));
175
		init_page_count(virt_to_page(addr));
176
		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
Linus Torvalds's avatar
Linus Torvalds committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190
		free_page(addr);
		totalram_pages++;
        }
        printk ("Freeing unused kernel memory: %ldk freed\n",
		((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10);
}

#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
{
        if (start < end)
                printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
        for (; start < end; start += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(start));
191
                init_page_count(virt_to_page(start));
Linus Torvalds's avatar
Linus Torvalds committed
192 193 194 195 196
                free_page(start);
                totalram_pages++;
        }
}
#endif