xref: /netbsd/sys/arch/sun2/sun2/control.c (revision ce099b40)
1*ce099b40Smartin /*	$NetBSD: control.c,v 1.6 2008/04/28 20:23:37 martin Exp $	*/
2ec984a04Sfredette 
3ec984a04Sfredette /*-
4ec984a04Sfredette  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5ec984a04Sfredette  * All rights reserved.
6ec984a04Sfredette  *
7ec984a04Sfredette  * This code is derived from software contributed to The NetBSD Foundation
8ec984a04Sfredette  * by Adam Glass, Gordon W. Ross, and Matthew Fredette.
9ec984a04Sfredette  *
10ec984a04Sfredette  * Redistribution and use in source and binary forms, with or without
11ec984a04Sfredette  * modification, are permitted provided that the following conditions
12ec984a04Sfredette  * are met:
13ec984a04Sfredette  * 1. Redistributions of source code must retain the above copyright
14ec984a04Sfredette  *    notice, this list of conditions and the following disclaimer.
15ec984a04Sfredette  * 2. Redistributions in binary form must reproduce the above copyright
16ec984a04Sfredette  *    notice, this list of conditions and the following disclaimer in the
17ec984a04Sfredette  *    documentation and/or other materials provided with the distribution.
18ec984a04Sfredette  *
19ec984a04Sfredette  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20ec984a04Sfredette  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21ec984a04Sfredette  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22ec984a04Sfredette  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23ec984a04Sfredette  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ec984a04Sfredette  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ec984a04Sfredette  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ec984a04Sfredette  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ec984a04Sfredette  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ec984a04Sfredette  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ec984a04Sfredette  * POSSIBILITY OF SUCH DAMAGE.
30ec984a04Sfredette  */
31ec984a04Sfredette 
32ed517291Slukem #include <sys/cdefs.h>
33*ce099b40Smartin __KERNEL_RCSID(0, "$NetBSD: control.c,v 1.6 2008/04/28 20:23:37 martin Exp $");
34ed517291Slukem 
35ec984a04Sfredette #include <sys/param.h>
36ec984a04Sfredette 
37ec984a04Sfredette #include <machine/pte.h>
38ec984a04Sfredette #include <sun2/sun2/control.h>
39ec984a04Sfredette 
40ec984a04Sfredette int
get_context(void)4110b1a7beSchs get_context(void)
42ec984a04Sfredette {
43ec984a04Sfredette 	return (get_control_byte(CONTEXT_REG) & CONTEXT_MASK);
44ec984a04Sfredette }
45ec984a04Sfredette 
46ec984a04Sfredette void
set_context(int c)4710b1a7beSchs set_context(int c)
48ec984a04Sfredette {
49ec984a04Sfredette 	set_control_byte(CONTEXT_REG, (c & CONTEXT_MASK));
50ec984a04Sfredette }
51ec984a04Sfredette 
52ec984a04Sfredette u_int
get_pte(vaddr_t va)5310b1a7beSchs get_pte(vaddr_t va)
54ec984a04Sfredette {
55ec984a04Sfredette 	u_int pte;
56ec984a04Sfredette 
57ec984a04Sfredette 	pte = get_control_word(CONTROL_ADDR_BUILD(PGMAP_BASE, va));
58ec984a04Sfredette 	if (pte & PG_VALID) {
59ec984a04Sfredette 		/*
60ec984a04Sfredette 		 * This clears bit 30 (the kernel readable bit, which
61ec984a04Sfredette 		 * should always be set), bit 28 (which should always
62ec984a04Sfredette 		 * be set), bit 26 (the user writable bit, which we
63ec984a04Sfredette 		 * always have tracking the kernel writable bit), and
64ec984a04Sfredette 		 * bit 25 (the fill-on-demand bit, which should always
65ec984a04Sfredette 		 * be set).  In the protection, this leaves bit 29
66ec984a04Sfredette 		 * (the kernel writable bit) and bit 27 (the user
67ec984a04Sfredette 		 * readable bit).  See pte.h for more about this
68ec984a04Sfredette 		 * hack.
69ec984a04Sfredette 		 */
70ec984a04Sfredette 		pte &= ~(0x56000000);
71ec984a04Sfredette 		/*
72ec984a04Sfredette 		 * Flip bit 27 (the user readable bit) to become bit
73ec984a04Sfredette 		 * 27 (the PG_SYSTEM bit).
74ec984a04Sfredette 		 */
75ec984a04Sfredette 		pte ^= (PG_SYSTEM);
76ec984a04Sfredette 	}
77ec984a04Sfredette 	return (pte);
78ec984a04Sfredette }
79ec984a04Sfredette 
80ec984a04Sfredette void
set_pte(vaddr_t va,u_int pte)8110b1a7beSchs set_pte(vaddr_t va, u_int pte)
82ec984a04Sfredette {
83ec984a04Sfredette 	if (pte & PG_VALID) {
84ec984a04Sfredette 		/* Clear bit 26 (the user writable bit).  */
85ec984a04Sfredette 		pte &= (~0x04000000);
86ec984a04Sfredette 		/*
87ec984a04Sfredette 		 * Flip bit 27 (the PG_SYSTEM bit) to become bit 27
88ec984a04Sfredette 		 * (the user readable bit).
89ec984a04Sfredette 		 */
90ec984a04Sfredette 		pte ^= (PG_SYSTEM);
91ec984a04Sfredette 		/*
92ec984a04Sfredette 		 * Always set bits 30 (the kernel readable bit), bit
93ec984a04Sfredette 		 * 28, and bit 25 (the fill-on-demand bit), and set
94ec984a04Sfredette 		 * bit 26 (the user writable bit) iff bit 29 (the
95ec984a04Sfredette 		 * kernel writable bit) is set *and* bit 27 (the user
96ec984a04Sfredette 		 * readable bit) is set.  This latter bit of logic is
97ec984a04Sfredette 		 * expressed in the bizarre second term below, chosen
98ec984a04Sfredette 		 * because it needs no branches.
99ec984a04Sfredette 		 */
100ec984a04Sfredette #if (PG_WRITE >> 2) != PG_SYSTEM
101ec984a04Sfredette #error	"PG_WRITE and PG_SYSTEM definitions don't match!"
102ec984a04Sfredette #endif
103ec984a04Sfredette 		pte |= 0x52000000
104ec984a04Sfredette 		    | ((((pte & PG_WRITE) >> 2) & pte) >> 1);
105ec984a04Sfredette 	}
106ec984a04Sfredette 	set_control_word(CONTROL_ADDR_BUILD(PGMAP_BASE, va), pte);
107ec984a04Sfredette }
108ec984a04Sfredette 
109ec984a04Sfredette int
get_segmap(vaddr_t va)11010b1a7beSchs get_segmap(vaddr_t va)
111ec984a04Sfredette {
112ec984a04Sfredette 	return (get_control_byte(CONTROL_ADDR_BUILD(SEGMAP_BASE, va)));
113ec984a04Sfredette }
114ec984a04Sfredette 
115bbb634caSfredette void
set_segmap(vaddr_t va,int sme)11610b1a7beSchs set_segmap(vaddr_t va, int sme)
117ec984a04Sfredette {
118ec984a04Sfredette 	set_control_byte(CONTROL_ADDR_BUILD(SEGMAP_BASE, va), sme);
119ec984a04Sfredette }
120