master
  1/*-
  2 * SPDX-License-Identifier: BSD-2-Clause
  3 *
  4 * Copyright (c) 2002-2006 Rice University
  5 * Copyright (c) 2007 Alan L. Cox <alc@cs.rice.edu>
  6 * All rights reserved.
  7 *
  8 * This software was developed for the FreeBSD Project by Alan L. Cox,
  9 * Olivier Crameri, Peter Druschel, Sitaram Iyer, and Juan Navarro.
 10 *
 11 * Redistribution and use in source and binary forms, with or without
 12 * modification, are permitted provided that the following conditions
 13 * are met:
 14 * 1. Redistributions of source code must retain the above copyright
 15 *    notice, this list of conditions and the following disclaimer.
 16 * 2. Redistributions in binary form must reproduce the above copyright
 17 *    notice, this list of conditions and the following disclaimer in the
 18 *    documentation and/or other materials provided with the distribution.
 19 *
 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 23 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 30 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31 * POSSIBILITY OF SUCH DAMAGE.
 32 */
 33
 34/*
 35 *	Physical memory system definitions
 36 */
 37
 38#ifndef	_VM_PHYS_H_
 39#define	_VM_PHYS_H_
 40
 41#ifdef _KERNEL
 42
 43#include <vm/_vm_phys.h>
 44
 45extern vm_paddr_t phys_avail[];
 46
 47/* Domains must be dense (non-sparse) and zero-based. */
 48struct mem_affinity {
 49	vm_paddr_t start;
 50	vm_paddr_t end;
 51	int domain;
 52};
 53#ifdef NUMA
 54extern struct mem_affinity *mem_affinity;
 55extern int *mem_locality;
 56#endif
 57
 58/*
 59 * The following functions are only to be used by the virtual memory system.
 60 */
 61void vm_phys_add_seg(vm_paddr_t start, vm_paddr_t end);
 62vm_page_t vm_phys_alloc_contig(int domain, u_long npages, vm_paddr_t low,
 63    vm_paddr_t high, u_long alignment, vm_paddr_t boundary);
 64vm_page_t vm_phys_alloc_freelist_pages(int domain, int freelist, int pool,
 65    int order);
 66int vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[]);
 67vm_page_t vm_phys_alloc_pages(int domain, int pool, int order);
 68int vm_phys_domain_match(int prefer, vm_paddr_t low, vm_paddr_t high);
 69void vm_phys_enqueue_contig(vm_page_t m, u_long npages);
 70int vm_phys_fictitious_reg_range(vm_paddr_t start, vm_paddr_t end,
 71    vm_memattr_t memattr);
 72void vm_phys_fictitious_unreg_range(vm_paddr_t start, vm_paddr_t end);
 73vm_page_t vm_phys_fictitious_to_vm_page(vm_paddr_t pa);
 74int vm_phys_find_range(vm_page_t bounds[], int segind, int domain,
 75    u_long npages, vm_paddr_t low, vm_paddr_t high);
 76void vm_phys_free_contig(vm_page_t m, u_long npages);
 77void vm_phys_free_pages(vm_page_t m, int order);
 78void vm_phys_init(void);
 79vm_page_t vm_phys_paddr_to_vm_page(vm_paddr_t pa);
 80void vm_phys_register_domains(int ndomains, struct mem_affinity *affinity,
 81    int *locality);
 82bool vm_phys_unfree_page(vm_page_t m);
 83int vm_phys_mem_affinity(int f, int t);
 84void vm_phys_early_add_seg(vm_paddr_t start, vm_paddr_t end);
 85vm_paddr_t vm_phys_early_alloc(int domain, size_t alloc_size);
 86void vm_phys_early_startup(void);
 87int vm_phys_avail_largest(void);
 88vm_paddr_t vm_phys_avail_size(int i);
 89bool vm_phys_is_dumpable(vm_paddr_t pa);
 90
 91static inline int
 92vm_phys_domain(vm_paddr_t pa)
 93{
 94#ifdef NUMA
 95	int i;
 96
 97	if (vm_ndomains == 1)
 98		return (0);
 99	for (i = 0; mem_affinity[i].end != 0; i++)
100		if (mem_affinity[i].start <= pa &&
101		    mem_affinity[i].end >= pa)
102			return (mem_affinity[i].domain);
103	return (-1);
104#else
105	return (0);
106#endif
107}
108
109/*
110 * Find the segind for the first segment at or after the given physical address.
111 */
112static inline int
113vm_phys_lookup_segind(vm_paddr_t pa)
114{
115	u_int hi, lo, mid;
116
117	lo = 0;
118	hi = vm_phys_nsegs;
119	while (lo != hi) {
120		/*
121		 * for i in [0, lo), segs[i].end <= pa
122		 * for i in [hi, nsegs), segs[i].end > pa
123		 */
124		mid = lo + (hi - lo) / 2;
125		if (vm_phys_segs[mid].end <= pa)
126			lo = mid + 1;
127		else
128			hi = mid;
129	}
130	return (lo);
131}
132
133/*
134 * Find the segment corresponding to the given physical address.
135 */
136static inline struct vm_phys_seg *
137vm_phys_paddr_to_seg(vm_paddr_t pa)
138{
139	struct vm_phys_seg *seg;
140	int segind;
141
142	segind = vm_phys_lookup_segind(pa);
143	if (segind < vm_phys_nsegs) {
144		seg = &vm_phys_segs[segind];
145		if (pa >= seg->start)
146			return (seg);
147	}
148	return (NULL);
149}
150
151#endif	/* _KERNEL */
152#endif	/* !_VM_PHYS_H_ */