summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/stand/common/mmu.c
blob: 9a554bd11f36d9e21e1d497c05312c414be1f6ab (plain)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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
163
164
165
166
167
168
169
170
171
172
173
174
175
/*	$OpenBSD: mmu.c,v 1.1 2010/06/29 21:33:54 miod Exp $	*/
/*	$NetBSD: mmu.c,v 1.8 2008/04/28 20:23:36 martin Exp $	*/

/*-
 * Copyright (c) 2003 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Paul Kranenburg.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/param.h>
#include <lib/libsa/stand.h>
#include <machine/ctlreg.h>
#include <machine/idprom.h>
#include <machine/pte.h>
#include <sparc/sparc/asm.h>
#include <sparc/stand/common/promdev.h>

static int sun4_mmu3l;	/* sun4 3-lvl MMU */
static int rcookie;	/* sun4 3-lvl MMU region resource */
static int scookie;	/* sun4/sun4c MMU segment resource */
static int obmem;	/* SRMMU on-board memory space */

static int pmap_map4(vaddr_t va, paddr_t pa, psize_t size);
static int pmap_extract4(vaddr_t va, paddr_t *ppa);
static int pmap_map_srmmu(vaddr_t va, paddr_t pa, psize_t size);
static int pmap_extract_srmmu(vaddr_t va, paddr_t *ppa);

int (*pmap_map)(vaddr_t va, paddr_t pa, psize_t size);
int (*pmap_extract)(vaddr_t va, paddr_t *ppa);

int
mmu_init(void)
{
	if (CPU_ISSUN4 || CPU_ISSUN4C) {
		pmap_map = pmap_map4;
		pmap_extract = pmap_extract4;
		if (CPU_ISSUN4) {
			/* Find out if we're on a 3-lvl sun4 MMU. */
			struct idprom *idp = prom_getidprom();
			if (idp->id_machine == ID_SUN4_400)
				sun4_mmu3l = 1;
		}
		/*
		 * XXX - we just guess which MMU cookies are free:
		 *	 region 0 maps [0-16MB]
		 *	 segment 0-16 map [0-4MB]
		 *	 the PROM mappings use high-valued cookies.
		 */
		rcookie = 2;
		scookie = 17;
	} else if (CPU_ISSUN4M || CPU_ISSUN4D) {
		char buf[32];
		pmap_map = pmap_map_srmmu;
		pmap_extract = pmap_extract_srmmu;
		snprintf(buf, sizeof buf, "obmem %lx L!", (u_long)&obmem);
		prom_interpret(buf);
	} else
		return (ENOTSUP);

	return (0);
}


/*
 * SUN4 & SUN4C VM routines.
 * Limited functionality wrt. MMU resource management.
 */

#define getpte4(va)		lda(va, ASI_PTE)
#define setpte4(va, pte)	sta(va, ASI_PTE, pte)

int
pmap_map4(vaddr_t va, paddr_t pa, psize_t size)
{
	u_int n = (size + NBPG - 1) >> PGSHIFT;
	u_int pte;

	if (sun4_mmu3l)
		setregmap((va & -NBPRG), rcookie++);

#ifdef DEBUG
	printf("Mapping %lx -> %lx (%d pages)\n", va, pa, n);
#endif
	setsegmap((va & -NBPSG), ++scookie);
	while (n--) {
		pte = PG_S | PG_V | PG_W | PG_NC | ((pa >> PGSHIFT) & PG_PFNUM);
		setpte4(va, pte);
		va += NBPG;
		pa += NBPG;
		if ((va & (NBPSG - 1)) == 0) {
#ifdef DEBUG
	printf("%d ", scookie);
#endif
			setsegmap(va, ++scookie);
		}
	}
#ifdef DEBUG
	printf("\n");
#endif
	return (0);
}

int
pmap_extract4(vaddr_t va, paddr_t *ppa)
{
	u_int pte;

	va &= -NBPG;
	pte = getpte4(va);
	if ((pte & PG_V) == 0)
		return (EFAULT);

	*ppa = (pte & PG_PFNUM) << PGSHIFT;
	return (0);
}


/*
 * SRMMU VM routines.
 * We use the PROM's Forth services to do all the hard work.
 */
int
pmap_map_srmmu(vaddr_t va, paddr_t pa, psize_t size)
{
	char buf[64];

	snprintf(buf, sizeof buf, "%lx %x %lx %lx map-pages",
	    pa, obmem, va, size);

#ifdef DEBUG
	printf("Mapping kernel: %s\n", buf);
#endif

	prom_interpret(buf);
	return (0);
}

int
pmap_extract_srmmu(vaddr_t va, paddr_t *ppa)
{
	char buf[32];
	u_int pte;

	va &= -NBPG;
	snprintf(buf, sizeof buf, "%lx pgmap@ %lx L!", va, (u_long)&pte);
	prom_interpret(buf);
	if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE)
		return (EFAULT);

	*ppa = (pte & SRMMU_PPNMASK) << SRMMU_PPNPASHIFT;
	return (0);
}