1/*
2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
49 *  School of Computer Science
50 *  Carnegie Mellon University
51 *  Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 */
58/*
59 *	File:	vm/pmap.h
60 *	Author:	Avadis Tevanian, Jr.
61 *	Date:	1985
62 *
63 *	Machine address mapping definitions -- machine-independent
64 *	section.  [For machine-dependent section, see "machine/pmap.h".]
65 */
66
67#ifndef	_VM_PMAP_H_
68#define _VM_PMAP_H_
69
70#include <mach/kern_return.h>
71#include <mach/vm_param.h>
72#include <mach/vm_types.h>
73#include <mach/vm_attributes.h>
74#include <mach/boolean.h>
75#include <mach/vm_prot.h>
76
77#ifdef	KERNEL_PRIVATE
78
79/*
80 *	The following is a description of the interface to the
81 *	machine-dependent "physical map" data structure.  The module
82 *	must provide a "pmap_t" data type that represents the
83 *	set of valid virtual-to-physical addresses for one user
84 *	address space.  [The kernel address space is represented
85 *	by a distinguished "pmap_t".]  The routines described manage
86 *	this type, install and update virtual-to-physical mappings,
87 *	and perform operations on physical addresses common to
88 *	many address spaces.
89 */
90
91/* Copy between a physical page and a virtual address */
92/* LP64todo - switch to vm_map_offset_t when it grows */
93extern kern_return_t 	copypv(
94				addr64_t source,
95				addr64_t sink,
96				unsigned int size,
97				int which);
98#define cppvPsnk        1
99#define cppvPsnkb      31
100#define cppvPsrc        2
101#define cppvPsrcb      30
102#define cppvFsnk        4
103#define cppvFsnkb      29
104#define cppvFsrc        8
105#define cppvFsrcb      28
106#define cppvNoModSnk   16
107#define cppvNoModSnkb  27
108#define cppvNoRefSrc   32
109#define cppvNoRefSrcb  26
110#define cppvKmap       64	/* Use the kernel's vm_map */
111#define cppvKmapb      25
112
113#ifdef	MACH_KERNEL_PRIVATE
114
115#include <machine/pmap.h>
116
117/*
118 *	Routines used for initialization.
119 *	There is traditionally also a pmap_bootstrap,
120 *	used very early by machine-dependent code,
121 *	but it is not part of the interface.
122 *
123 *	LP64todo -
124 *	These interfaces are tied to the size of the
125 *	kernel pmap - and therefore use the "local"
126 *	vm_offset_t, etc... types.
127 */
128
129extern void 		*pmap_steal_memory(vm_size_t size);
130						/* During VM initialization,
131						 * steal a chunk of memory.
132						 */
133extern unsigned int	pmap_free_pages(void);	/* During VM initialization,
134						 * report remaining unused
135						 * physical pages.
136						 */
137extern void		pmap_startup(
138				vm_offset_t *startp,
139				vm_offset_t *endp);
140						/* During VM initialization,
141						 * use remaining physical pages
142						 * to allocate page frames.
143						 */
144extern void		pmap_init(void);
145						/* Initialization,
146						 * after kernel runs
147						 * in virtual memory.
148						 */
149
150extern void 		mapping_adjust(void);	/* Adjust free mapping count */
151
152extern void 		mapping_free_prime(void); /* Primes the mapping block release list */
153
154#ifndef	MACHINE_PAGES
155/*
156 *	If machine/pmap.h defines MACHINE_PAGES, it must implement
157 *	the above functions.  The pmap module has complete control.
158 *	Otherwise, it must implement
159 *		pmap_free_pages
160 *		pmap_virtual_space
161 *		pmap_next_page
162 *		pmap_init
163 *	and vm/vm_resident.c implements pmap_steal_memory and pmap_startup
164 *	using pmap_free_pages, pmap_next_page, pmap_virtual_space,
165 *	and pmap_enter.  pmap_free_pages may over-estimate the number
166 *	of unused physical pages, and pmap_next_page may return FALSE
167 *	to indicate that there are no more unused pages to return.
168 *	However, for best performance pmap_free_pages should be accurate.
169 */
170
171extern boolean_t	pmap_next_page(ppnum_t *pnum);
172extern boolean_t	pmap_next_page_hi(ppnum_t *pnum);
173						/* During VM initialization,
174						 * return the next unused
175						 * physical page.
176						 */
177extern void		pmap_virtual_space(
178					vm_offset_t	*virtual_start,
179					vm_offset_t	*virtual_end);
180						/* During VM initialization,
181						 * report virtual space
182						 * available for the kernel.
183						 */
184#endif	/* MACHINE_PAGES */
185
186/*
187 *	Routines to manage the physical map data structure.
188 */
189extern pmap_t		pmap_create(	/* Create a pmap_t. */
190				ledger_t	ledger,
191				vm_map_size_t	size,
192				__unused boolean_t	is_64bit);
193extern pmap_t		(pmap_kernel)(void);	/* Return the kernel's pmap */
194extern void		pmap_reference(pmap_t pmap);	/* Gain a reference. */
195extern void		pmap_destroy(pmap_t pmap); /* Release a reference. */
196extern void		pmap_switch(pmap_t);
197
198
199extern void		pmap_enter(	/* Enter a mapping */
200				pmap_t		pmap,
201				vm_map_offset_t	v,
202				ppnum_t		pn,
203				vm_prot_t	prot,
204				vm_prot_t	fault_type,
205				unsigned int	flags,
206				boolean_t	wired);
207
208extern kern_return_t	pmap_enter_options(
209					   pmap_t pmap,
210					   vm_map_offset_t v,
211					   ppnum_t pn,
212					   vm_prot_t prot,
213					   vm_prot_t fault_type,
214					   unsigned int flags,
215					   boolean_t wired,
216					   unsigned int options,
217					   void *arg);
218
219extern void		pmap_remove_some_phys(
220				pmap_t		pmap,
221				ppnum_t		pn);
222
223
224/*
225 *	Routines that operate on physical addresses.
226 */
227
228extern void		pmap_page_protect(	/* Restrict access to page. */
229				ppnum_t	phys,
230				vm_prot_t	prot);
231
232extern void		pmap_page_protect_options(	/* Restrict access to page. */
233				ppnum_t	phys,
234				vm_prot_t	prot,
235				unsigned int 	options,
236				void		*arg);
237
238extern void		(pmap_zero_page)(
239				ppnum_t		pn);
240
241extern void		(pmap_zero_part_page)(
242				ppnum_t		pn,
243				vm_offset_t     offset,
244				vm_size_t       len);
245
246extern void		(pmap_copy_page)(
247				ppnum_t		src,
248				ppnum_t		dest);
249
250extern void		(pmap_copy_part_page)(
251				ppnum_t		src,
252				vm_offset_t	src_offset,
253				ppnum_t		dst,
254				vm_offset_t	dst_offset,
255				vm_size_t	len);
256
257extern void		(pmap_copy_part_lpage)(
258				vm_offset_t	src,
259				ppnum_t		dst,
260				vm_offset_t	dst_offset,
261				vm_size_t	len);
262
263extern void		(pmap_copy_part_rpage)(
264				ppnum_t		src,
265				vm_offset_t	src_offset,
266				vm_offset_t	dst,
267				vm_size_t	len);
268
269extern unsigned int (pmap_disconnect)(	/* disconnect mappings and return reference and change */
270				ppnum_t		phys);
271
272extern unsigned int (pmap_disconnect_options)(	/* disconnect mappings and return reference and change */
273				ppnum_t		phys,
274				unsigned int	options,
275	                        void		*arg);
276
277extern kern_return_t	(pmap_attribute_cache_sync)(  /* Flush appropriate
278						       * cache based on
279						       * page number sent */
280				ppnum_t		pn,
281				vm_size_t	size,
282				vm_machine_attribute_t attribute,
283				vm_machine_attribute_val_t* value);
284
285extern unsigned int	(pmap_cache_attributes)(
286				ppnum_t		pn);
287
288/*
289 * Set (override) cache attributes for the specified physical page
290 */
291extern	void		pmap_set_cache_attributes(
292				ppnum_t,
293				unsigned int);
294extern void pmap_sync_page_data_phys(ppnum_t pa);
295extern void pmap_sync_page_attributes_phys(ppnum_t pa);
296
297/*
298 * debug/assertions. pmap_verify_free returns true iff
299 * the given physical page is mapped into no pmap.
300 */
301extern boolean_t	pmap_verify_free(ppnum_t pn);
302
303/*
304 *	Statistics routines
305 */
306extern int		(pmap_resident_count)(pmap_t pmap);
307extern int		(pmap_resident_max)(pmap_t pmap);
308
309/*
310 *	Sundry required (internal) routines
311 */
312#ifdef CURRENTLY_UNUSED_AND_UNTESTED
313extern void		pmap_collect(pmap_t pmap);/* Perform garbage
314						 * collection, if any */
315#endif
316/*
317 *	Optional routines
318 */
319extern void		(pmap_copy)(		/* Copy range of mappings,
320						 * if desired. */
321				pmap_t		dest,
322				pmap_t		source,
323				vm_map_offset_t	dest_va,
324				vm_map_size_t	size,
325				vm_map_offset_t	source_va);
326
327extern kern_return_t	(pmap_attribute)(	/* Get/Set special memory
328						 * attributes */
329				pmap_t		pmap,
330				vm_map_offset_t	va,
331				vm_map_size_t	size,
332				vm_machine_attribute_t  attribute,
333				vm_machine_attribute_val_t* value);
334
335/*
336 * Routines defined as macros.
337 */
338#ifndef PMAP_ACTIVATE_USER
339#ifndef	PMAP_ACTIVATE
340#define PMAP_ACTIVATE_USER(thr, cpu)
341#else	/* PMAP_ACTIVATE */
342#define PMAP_ACTIVATE_USER(thr, cpu) {			\
343	pmap_t  pmap;						\
344								\
345	pmap = (thr)->map->pmap;				\
346	if (pmap != pmap_kernel())				\
347		PMAP_ACTIVATE(pmap, (thr), (cpu));		\
348}
349#endif  /* PMAP_ACTIVATE */
350#endif  /* PMAP_ACTIVATE_USER */
351
352#ifndef PMAP_DEACTIVATE_USER
353#ifndef PMAP_DEACTIVATE
354#define PMAP_DEACTIVATE_USER(thr, cpu)
355#else	/* PMAP_DEACTIVATE */
356#define PMAP_DEACTIVATE_USER(thr, cpu) {			\
357	pmap_t  pmap;						\
358								\
359	pmap = (thr)->map->pmap;				\
360	if ((pmap) != pmap_kernel())			\
361		PMAP_DEACTIVATE(pmap, (thr), (cpu));	\
362}
363#endif	/* PMAP_DEACTIVATE */
364#endif  /* PMAP_DEACTIVATE_USER */
365
366#ifndef	PMAP_ACTIVATE_KERNEL
367#ifndef PMAP_ACTIVATE
368#define	PMAP_ACTIVATE_KERNEL(cpu)
369#else	/* PMAP_ACTIVATE */
370#define	PMAP_ACTIVATE_KERNEL(cpu)			\
371		PMAP_ACTIVATE(pmap_kernel(), THREAD_NULL, cpu)
372#endif	/* PMAP_ACTIVATE */
373#endif	/* PMAP_ACTIVATE_KERNEL */
374
375#ifndef	PMAP_DEACTIVATE_KERNEL
376#ifndef PMAP_DEACTIVATE
377#define	PMAP_DEACTIVATE_KERNEL(cpu)
378#else	/* PMAP_DEACTIVATE */
379#define	PMAP_DEACTIVATE_KERNEL(cpu)			\
380		PMAP_DEACTIVATE(pmap_kernel(), THREAD_NULL, cpu)
381#endif	/* PMAP_DEACTIVATE */
382#endif	/* PMAP_DEACTIVATE_KERNEL */
383
384#ifndef	PMAP_ENTER
385/*
386 *	Macro to be used in place of pmap_enter()
387 */
388#define PMAP_ENTER(pmap, virtual_address, page, protection, fault_type, flags, wired) \
389	MACRO_BEGIN							\
390	pmap_t		__pmap = (pmap);				\
391	vm_page_t	__page = (page);				\
392	int		__options = 0;					\
393									\
394	PMAP_ENTER_CHECK(__pmap, __page)				\
395	if (__page->object->internal) {					\
396		__options |= PMAP_OPTIONS_INTERNAL;			\
397	}								\
398	if (__page->reusable || __page->object->all_reusable) {		\
399		__options |= PMAP_OPTIONS_REUSABLE;			\
400	}								\
401	(void) pmap_enter_options(__pmap,				\
402				  (virtual_address),			\
403				  __page->phys_page,			\
404				  (protection),				\
405				  (fault_type),				\
406				  (flags),				\
407				  (wired),				\
408				  __options,				\
409				  NULL);				\
410	MACRO_END
411#endif	/* !PMAP_ENTER */
412
413#ifndef	PMAP_ENTER_OPTIONS
414#define PMAP_ENTER_OPTIONS(pmap, virtual_address, page, protection,	\
415			   fault_type, flags, wired, options, result)	\
416	MACRO_BEGIN							\
417	pmap_t		__pmap = (pmap);				\
418	vm_page_t	__page = (page);				\
419	int		__extra_options = 0;				\
420									\
421	PMAP_ENTER_CHECK(__pmap, __page)				\
422	if (__page->object->internal) {					\
423		__extra_options |= PMAP_OPTIONS_INTERNAL;		\
424	}								\
425	if (__page->reusable || __page->object->all_reusable) {		\
426		__extra_options |= PMAP_OPTIONS_REUSABLE;		\
427	}								\
428	result = pmap_enter_options(__pmap,				\
429				    (virtual_address),			\
430				    __page->phys_page,			\
431				    (protection),			\
432				    (fault_type),			\
433				    (flags),				\
434				    (wired),				\
435				    (options) | __extra_options,	\
436				    NULL);				\
437	MACRO_END
438#endif	/* !PMAP_ENTER_OPTIONS */
439
440#ifndef PMAP_SET_CACHE_ATTR
441#define PMAP_SET_CACHE_ATTR(mem, object, cache_attr, batch_pmap_op)		\
442	MACRO_BEGIN								\
443		if (!batch_pmap_op) {						\
444			pmap_set_cache_attributes(mem->phys_page, cache_attr);	\
445			object->set_cache_attr = TRUE;				\
446		}								\
447	MACRO_END
448#endif	/* PMAP_SET_CACHE_ATTR */
449
450#ifndef PMAP_BATCH_SET_CACHE_ATTR
451#define PMAP_BATCH_SET_CACHE_ATTR(object, user_page_list,			\
452					cache_attr, num_pages, batch_pmap_op)	\
453	MACRO_BEGIN								\
454		if ((batch_pmap_op)) {						\
455			unsigned int __page_idx=0;				\
456			while (__page_idx < (num_pages)) {			\
457				pmap_set_cache_attributes(			\
458					user_page_list[__page_idx].phys_addr,	\
459					(cache_attr));				\
460				__page_idx++;					\
461			}							\
462			(object)->set_cache_attr = TRUE;			\
463		}								\
464	MACRO_END
465#endif	/* PMAP_BATCH_SET_CACHE_ATTR */
466
467#define PMAP_ENTER_CHECK(pmap, page)					\
468{									\
469	if ((pmap) != kernel_pmap) {					\
470		ASSERT_PAGE_DECRYPTED(page);				\
471	}								\
472	if ((page)->error) {						\
473		panic("VM page %p should not have an error\n",		\
474			(page));					\
475	}								\
476}
477
478/*
479 *	Routines to manage reference/modify bits based on
480 *	physical addresses, simulating them if not provided
481 *	by the hardware.
482 */
483struct pfc {
484	long	pfc_cpus;
485	long	pfc_invalid_global;
486};
487
488typedef	struct pfc	pmap_flush_context;
489
490				/* Clear reference bit */
491extern void		pmap_clear_reference(ppnum_t	 pn);
492				/* Return reference bit */
493extern boolean_t	(pmap_is_referenced)(ppnum_t	 pn);
494				/* Set modify bit */
495extern void             pmap_set_modify(ppnum_t	 pn);
496				/* Clear modify bit */
497extern void		pmap_clear_modify(ppnum_t pn);
498				/* Return modify bit */
499extern boolean_t	pmap_is_modified(ppnum_t pn);
500				/* Return modified and referenced bits */
501extern unsigned int pmap_get_refmod(ppnum_t pn);
502				/* Clear modified and referenced bits */
503extern void			pmap_clear_refmod(ppnum_t pn, unsigned int mask);
504#define VM_MEM_MODIFIED		0x01	/* Modified bit */
505#define VM_MEM_REFERENCED	0x02	/* Referenced bit */
506extern void			pmap_clear_refmod_options(ppnum_t pn, unsigned int mask, unsigned int options, void *);
507
508
509extern void pmap_flush_context_init(pmap_flush_context *);
510extern void pmap_flush(pmap_flush_context *);
511
512/*
513 *	Routines that operate on ranges of virtual addresses.
514 */
515extern void		pmap_protect(	/* Change protections. */
516				pmap_t		map,
517				vm_map_offset_t	s,
518				vm_map_offset_t	e,
519				vm_prot_t	prot);
520
521extern void		pmap_protect_options(	/* Change protections. */
522				pmap_t		map,
523				vm_map_offset_t	s,
524				vm_map_offset_t	e,
525				vm_prot_t	prot,
526				unsigned int	options,
527				void 		*arg);
528
529extern void		(pmap_pageable)(
530				pmap_t		pmap,
531				vm_map_offset_t	start,
532				vm_map_offset_t	end,
533				boolean_t	pageable);
534
535
536extern uint64_t pmap_nesting_size_min;
537extern uint64_t pmap_nesting_size_max;
538
539extern kern_return_t pmap_nest(pmap_t,
540			       pmap_t,
541			       addr64_t,
542			       addr64_t,
543			       uint64_t);
544extern kern_return_t pmap_unnest(pmap_t,
545				 addr64_t,
546				 uint64_t);
547extern boolean_t pmap_adjust_unnest_parameters(pmap_t, vm_map_offset_t *, vm_map_offset_t *);
548#endif	/* MACH_KERNEL_PRIVATE */
549
550extern boolean_t	pmap_is_noencrypt(ppnum_t);
551extern void		pmap_set_noencrypt(ppnum_t pn);
552extern void		pmap_clear_noencrypt(ppnum_t pn);
553
554/*
555 * JMM - This portion is exported to other kernel components right now,
556 * but will be pulled back in the future when the needed functionality
557 * is provided in a cleaner manner.
558 */
559
560extern pmap_t	kernel_pmap;			/* The kernel's map */
561#define		pmap_kernel()	(kernel_pmap)
562
563/* machine independent WIMG bits */
564
565#define VM_MEM_GUARDED 		0x1		/* (G) Guarded Storage */
566#define VM_MEM_COHERENT		0x2		/* (M) Memory Coherency */
567#define VM_MEM_NOT_CACHEABLE	0x4		/* (I) Cache Inhibit */
568#define VM_MEM_WRITE_THROUGH	0x8		/* (W) Write-Through */
569
570#define VM_WIMG_USE_DEFAULT	0x80
571#define VM_WIMG_MASK		0xFF
572
573#define VM_MEM_SUPERPAGE	0x100		/* map a superpage instead of a base page */
574#define VM_MEM_STACK		0x200
575
576#define PMAP_OPTIONS_NOWAIT	0x1		/* don't block, return
577						 * KERN_RESOURCE_SHORTAGE
578						 * instead */
579#define PMAP_OPTIONS_NOENTER	0x2		/* expand pmap if needed
580						 * but don't enter mapping
581						 */
582#define PMAP_OPTIONS_COMPRESSOR 0x4		/* credit the compressor for
583						 * this operation */
584#define PMAP_OPTIONS_INTERNAL	0x8		/* page from internal object */
585#define PMAP_OPTIONS_REUSABLE	0x10		/* page is "reusable" */
586#define PMAP_OPTIONS_NOFLUSH	0x20		/* delay flushing of pmap */
587#define PMAP_OPTIONS_NOREFMOD	0x40		/* don't need ref/mod on disconnect */
588#define PMAP_OPTIONS_REMOVE	0x100		/* removing a mapping */
589
590#if	!defined(__LP64__)
591extern vm_offset_t	pmap_extract(pmap_t pmap,
592				vm_map_offset_t va);
593#endif
594extern void		pmap_change_wiring(	/* Specify pageability */
595				pmap_t		pmap,
596				vm_map_offset_t	va,
597				boolean_t	wired);
598
599/* LP64todo - switch to vm_map_offset_t when it grows */
600extern void		pmap_remove(	/* Remove mappings. */
601				pmap_t		map,
602				vm_map_offset_t	s,
603				vm_map_offset_t	e);
604
605extern void		pmap_remove_options(	/* Remove mappings. */
606				pmap_t		map,
607				vm_map_offset_t	s,
608				vm_map_offset_t	e,
609				int		options);
610
611extern void		pmap_reusable(
612				pmap_t		map,
613				vm_map_offset_t	s,
614				vm_map_offset_t	e,
615				boolean_t	reusable);
616
617extern void		fillPage(ppnum_t pa, unsigned int fill);
618
619extern void pmap_map_sharedpage(task_t task, pmap_t pmap);
620extern void pmap_unmap_sharedpage(pmap_t pmap);
621
622#if defined(__LP64__)
623void pmap_pre_expand(pmap_t pmap, vm_map_offset_t vaddr);
624#endif
625
626unsigned int pmap_query_resident(pmap_t pmap,
627				 vm_map_offset_t s,
628				 vm_map_offset_t e);
629
630#endif  /* KERNEL_PRIVATE */
631
632#endif	/* _VM_PMAP_H_ */
633