init.c 5.66 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
static void __init setup_ro_region(void)
{
	pgd_t *pgd;
84
	pud_t *pud;
85 86 87 88 89
	pmd_t *pmd;
	pte_t *pte;
	pte_t new_pte;
	unsigned long address, end;

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

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

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

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

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

132
	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
133
#ifdef CONFIG_ZONE_DMA
134
	max_zone_pfns[ZONE_DMA] = PFN_DOWN(MAX_DMA_ADDRESS);
135
#endif
136 137
	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
	free_area_init_nodes(max_zone_pfns);
Linus Torvalds's avatar
Linus Torvalds committed
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 163 164
}

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);
165
	printk("Write protected kernel read-only data: %#lx - %#lx\n",
166 167
	       (unsigned long)&_stext,
	       PFN_ALIGN((unsigned long)&_eshared) - 1);
Linus Torvalds's avatar
Linus Torvalds committed
168 169 170 171 172 173 174 175 176
}

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));
177
		init_page_count(virt_to_page(addr));
178
		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
Linus Torvalds's avatar
Linus Torvalds committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192
		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));
193
                init_page_count(virt_to_page(start));
Linus Torvalds's avatar
Linus Torvalds committed
194 195 196 197 198
                free_page(start);
                totalram_pages++;
        }
}
#endif