| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: uvm_page.c,v 1.153.2.56 2010/10/22 07:22:57 uebayasi Exp $ */ | | 1 | /* $NetBSD: uvm_page.c,v 1.153.2.57 2010/10/27 14:51:29 uebayasi Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2010 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -87,27 +87,27 @@ | | | @@ -87,27 +87,27 @@ |
87 | * School of Computer Science | | 87 | * School of Computer Science |
88 | * Carnegie Mellon University | | 88 | * Carnegie Mellon University |
89 | * Pittsburgh PA 15213-3890 | | 89 | * Pittsburgh PA 15213-3890 |
90 | * | | 90 | * |
91 | * any improvements or extensions that they make and grant Carnegie the | | 91 | * any improvements or extensions that they make and grant Carnegie the |
92 | * rights to redistribute these changes. | | 92 | * rights to redistribute these changes. |
93 | */ | | 93 | */ |
94 | | | 94 | |
95 | /* | | 95 | /* |
96 | * uvm_page.c: page ops. | | 96 | * uvm_page.c: page ops. |
97 | */ | | 97 | */ |
98 | | | 98 | |
99 | #include <sys/cdefs.h> | | 99 | #include <sys/cdefs.h> |
100 | __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.56 2010/10/22 07:22:57 uebayasi Exp $"); | | 100 | __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v 1.153.2.57 2010/10/27 14:51:29 uebayasi Exp $"); |
101 | | | 101 | |
102 | #include "opt_ddb.h" | | 102 | #include "opt_ddb.h" |
103 | #include "opt_uvmhist.h" | | 103 | #include "opt_uvmhist.h" |
104 | #include "opt_readahead.h" | | 104 | #include "opt_readahead.h" |
105 | #include "opt_xip.h" | | 105 | #include "opt_xip.h" |
106 | | | 106 | |
107 | #include <sys/param.h> | | 107 | #include <sys/param.h> |
108 | #include <sys/systm.h> | | 108 | #include <sys/systm.h> |
109 | #include <sys/malloc.h> | | 109 | #include <sys/malloc.h> |
110 | #include <sys/sched.h> | | 110 | #include <sys/sched.h> |
111 | #include <sys/kernel.h> | | 111 | #include <sys/kernel.h> |
112 | #include <sys/vnode.h> | | 112 | #include <sys/vnode.h> |
113 | #include <sys/proc.h> | | 113 | #include <sys/proc.h> |
| @@ -124,33 +124,31 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v | | | @@ -124,33 +124,31 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_page.c,v |
124 | | | 124 | |
125 | /* | | 125 | /* |
126 | * physical memory config is stored in vm_physmem. | | 126 | * physical memory config is stored in vm_physmem. |
127 | */ | | 127 | */ |
128 | | | 128 | |
129 | SIMPLEQ_HEAD(vm_physseg_freelist, vm_physseg); | | 129 | SIMPLEQ_HEAD(vm_physseg_freelist, vm_physseg); |
130 | | | 130 | |
131 | struct vm_physseg *vm_physmem_ptrs[VM_PHYSSEG_MAX]; | | 131 | struct vm_physseg *vm_physmem_ptrs[VM_PHYSSEG_MAX]; |
132 | int vm_nphysmem = 0; | | 132 | int vm_nphysmem = 0; |
133 | static struct vm_physseg vm_physmem_store[VM_PHYSSEG_MAX]; | | 133 | static struct vm_physseg vm_physmem_store[VM_PHYSSEG_MAX]; |
134 | static struct vm_physseg_freelist vm_physmem_freelist = | | 134 | static struct vm_physseg_freelist vm_physmem_freelist = |
135 | SIMPLEQ_HEAD_INITIALIZER(vm_physmem_freelist); | | 135 | SIMPLEQ_HEAD_INITIALIZER(vm_physmem_freelist); |
136 | | | 136 | |
137 | #ifdef XIP | | | |
138 | struct vm_physseg *vm_physdev_ptrs[VM_PHYSSEG_MAX]; | | 137 | struct vm_physseg *vm_physdev_ptrs[VM_PHYSSEG_MAX]; |
139 | int vm_nphysdev = 0; | | 138 | int vm_nphysdev = 0; |
140 | static struct vm_physseg vm_physdev_store[VM_PHYSSEG_MAX]; | | 139 | static struct vm_physseg vm_physdev_store[VM_PHYSSEG_MAX]; |
141 | static struct vm_physseg_freelist vm_physdev_freelist = | | 140 | static struct vm_physseg_freelist vm_physdev_freelist = |
142 | SIMPLEQ_HEAD_INITIALIZER(vm_physdev_freelist); | | 141 | SIMPLEQ_HEAD_INITIALIZER(vm_physdev_freelist); |
143 | #endif | | | |
144 | | | 142 | |
145 | /* | | 143 | /* |
146 | * Some supported CPUs in a given architecture don't support all | | 144 | * Some supported CPUs in a given architecture don't support all |
147 | * of the things necessary to do idle page zero'ing efficiently. | | 145 | * of the things necessary to do idle page zero'ing efficiently. |
148 | * We therefore provide a way to enable it from machdep code here. | | 146 | * We therefore provide a way to enable it from machdep code here. |
149 | */ | | 147 | */ |
150 | bool vm_page_zero_enable = false; | | 148 | bool vm_page_zero_enable = false; |
151 | | | 149 | |
152 | /* | | 150 | /* |
153 | * number of pages per-CPU to reserve for the kernel. | | 151 | * number of pages per-CPU to reserve for the kernel. |
154 | */ | | 152 | */ |
155 | int vm_page_reserve_kernel = 5; | | 153 | int vm_page_reserve_kernel = 5; |
156 | | | 154 | |
| @@ -822,27 +820,26 @@ uvm_page_physload(paddr_t start, paddr_t | | | @@ -822,27 +820,26 @@ uvm_page_physload(paddr_t start, paddr_t |
822 | void | | 820 | void |
823 | uvm_page_physunload(void *cookie) | | 821 | uvm_page_physunload(void *cookie) |
824 | { | | 822 | { |
825 | struct vm_physseg *seg = cookie; | | 823 | struct vm_physseg *seg = cookie; |
826 | | | 824 | |
827 | panic("memory unload is not supported yet"); | | 825 | panic("memory unload is not supported yet"); |
828 | | | 826 | |
829 | /* XXX */ | | 827 | /* XXX */ |
830 | | | 828 | |
831 | uvm_physseg_free(&vm_physmem_freelist, vm_physmem_ptrs, seg); | | 829 | uvm_physseg_free(&vm_physmem_freelist, vm_physmem_ptrs, seg); |
832 | vm_nphysmem--; | | 830 | vm_nphysmem--; |
833 | } | | 831 | } |
834 | | | 832 | |
835 | #ifdef XIP | | | |
836 | void * | | 833 | void * |
837 | uvm_page_physload_device(paddr_t start, paddr_t end, paddr_t avail_start, | | 834 | uvm_page_physload_device(paddr_t start, paddr_t end, paddr_t avail_start, |
838 | paddr_t avail_end, int prot, int flags) | | 835 | paddr_t avail_end, int prot, int flags) |
839 | { | | 836 | { |
840 | struct vm_physseg *seg; | | 837 | struct vm_physseg *seg; |
841 | int i; | | 838 | int i; |
842 | | | 839 | |
843 | seg = uvm_physseg_alloc(&vm_physdev_freelist, vm_physdev_ptrs, | | 840 | seg = uvm_physseg_alloc(&vm_physdev_freelist, vm_physdev_ptrs, |
844 | vm_nphysdev, start, end); | | 841 | vm_nphysdev, start, end); |
845 | KASSERT(seg != NULL); | | 842 | KASSERT(seg != NULL); |
846 | | | 843 | |
847 | seg->prot = prot; | | 844 | seg->prot = prot; |
848 | seg->flags = flags; /* XXXUEBS BUS_SPACE_MAP_* */ | | 845 | seg->flags = flags; /* XXXUEBS BUS_SPACE_MAP_* */ |
| @@ -895,27 +892,26 @@ uvm_page_physunload_device(void *cookie) | | | @@ -895,27 +892,26 @@ uvm_page_physunload_device(void *cookie) |
895 | { | | 892 | { |
896 | struct vm_physseg *seg = cookie; | | 893 | struct vm_physseg *seg = cookie; |
897 | | | 894 | |
898 | #ifdef __HAVE_PMAP_PHYSSEG | | 895 | #ifdef __HAVE_PMAP_PHYSSEG |
899 | #ifdef __HAVE_PMAP_PHYSSEG_INIT | | 896 | #ifdef __HAVE_PMAP_PHYSSEG_INIT |
900 | pmap_physseg_fini(seg); | | 897 | pmap_physseg_fini(seg); |
901 | #endif | | 898 | #endif |
902 | #endif | | 899 | #endif |
903 | | | 900 | |
904 | kmem_free(seg->pgs, sizeof(struct vm_page) * (seg->end - seg->start)); | | 901 | kmem_free(seg->pgs, sizeof(struct vm_page) * (seg->end - seg->start)); |
905 | uvm_physseg_free(&vm_physdev_freelist, vm_physdev_ptrs, seg); | | 902 | uvm_physseg_free(&vm_physdev_freelist, vm_physdev_ptrs, seg); |
906 | vm_nphysdev--; | | 903 | vm_nphysdev--; |
907 | } | | 904 | } |
908 | #endif | | | |
909 | | | 905 | |
910 | int uvm_physseg_inited; | | 906 | int uvm_physseg_inited; |
911 | | | 907 | |
912 | static struct vm_physseg * | | 908 | static struct vm_physseg * |
913 | uvm_physseg_alloc(struct vm_physseg_freelist *freelist, | | 909 | uvm_physseg_alloc(struct vm_physseg_freelist *freelist, |
914 | struct vm_physseg **segs, int nsegs, | | 910 | struct vm_physseg **segs, int nsegs, |
915 | const paddr_t start, const paddr_t end) | | 911 | const paddr_t start, const paddr_t end) |
916 | { | | 912 | { |
917 | struct vm_physseg *ps; | | 913 | struct vm_physseg *ps; |
918 | | | 914 | |
919 | if (uvmexp.pagesize == 0) | | 915 | if (uvmexp.pagesize == 0) |
920 | panic("uvm_page_physload: page size not set!"); | | 916 | panic("uvm_page_physload: page size not set!"); |
921 | if (start >= end) | | 917 | if (start >= end) |
| @@ -952,32 +948,30 @@ uvm_physseg_free(struct vm_physseg_freel | | | @@ -952,32 +948,30 @@ uvm_physseg_free(struct vm_physseg_freel |
952 | uvm_physseg_remove(segs, seg); | | 948 | uvm_physseg_remove(segs, seg); |
953 | SIMPLEQ_INSERT_TAIL(freelist, seg, list); | | 949 | SIMPLEQ_INSERT_TAIL(freelist, seg, list); |
954 | } | | 950 | } |
955 | | | 951 | |
956 | static void | | 952 | static void |
957 | uvm_physseg_init(void) | | 953 | uvm_physseg_init(void) |
958 | { | | 954 | { |
959 | int lcv; | | 955 | int lcv; |
960 | | | 956 | |
961 | for (lcv = 0; lcv < VM_PHYSSEG_MAX; lcv++) { | | 957 | for (lcv = 0; lcv < VM_PHYSSEG_MAX; lcv++) { |
962 | SIMPLEQ_INSERT_TAIL(&vm_physmem_freelist, | | 958 | SIMPLEQ_INSERT_TAIL(&vm_physmem_freelist, |
963 | &vm_physmem_store[lcv], list); | | 959 | &vm_physmem_store[lcv], list); |
964 | } | | 960 | } |
965 | #ifdef XIP | | | |
966 | for (lcv = 0; lcv < VM_PHYSSEG_MAX; lcv++) { | | 961 | for (lcv = 0; lcv < VM_PHYSSEG_MAX; lcv++) { |
967 | SIMPLEQ_INSERT_TAIL(&vm_physdev_freelist, | | 962 | SIMPLEQ_INSERT_TAIL(&vm_physdev_freelist, |
968 | &vm_physdev_store[lcv], list); | | 963 | &vm_physdev_store[lcv], list); |
969 | } | | 964 | } |
970 | #endif | | | |
971 | } | | 965 | } |
972 | | | 966 | |
973 | static void | | 967 | static void |
974 | uvm_physseg_insert(struct vm_physseg *ps, | | 968 | uvm_physseg_insert(struct vm_physseg *ps, |
975 | struct vm_physseg **segs, int nsegs) | | 969 | struct vm_physseg **segs, int nsegs) |
976 | { | | 970 | { |
977 | | | 971 | |
978 | #if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) | | 972 | #if (VM_PHYSSEG_STRAT == VM_PSTRAT_RANDOM) |
979 | /* random: put it at the end (easy!) */ | | 973 | /* random: put it at the end (easy!) */ |
980 | segs[nsegs] = ps; | | 974 | segs[nsegs] = ps; |
981 | #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) | | 975 | #elif (VM_PHYSSEG_STRAT == VM_PSTRAT_BSEARCH) |
982 | { | | 976 | { |
983 | int lcv; | | 977 | int lcv; |
| @@ -1049,35 +1043,33 @@ static inline bool vm_physseg_within_p(s | | | @@ -1049,35 +1043,33 @@ static inline bool vm_physseg_within_p(s |
1049 | static inline bool vm_physseg_ge_p(struct vm_physseg *, int, paddr_t, | | 1043 | static inline bool vm_physseg_ge_p(struct vm_physseg *, int, paddr_t, |
1050 | const struct vm_page *, int *); | | 1044 | const struct vm_page *, int *); |
1051 | static inline bool vm_physseg_lt_p(struct vm_physseg *, int, paddr_t, | | 1045 | static inline bool vm_physseg_lt_p(struct vm_physseg *, int, paddr_t, |
1052 | const struct vm_page *, int *); | | 1046 | const struct vm_page *, int *); |
1053 | | | 1047 | |
1054 | int | | 1048 | int |
1055 | vm_physseg_find(paddr_t pframe, int *offp) | | 1049 | vm_physseg_find(paddr_t pframe, int *offp) |
1056 | { | | 1050 | { |
1057 | | | 1051 | |
1058 | return VM_PHYSSEG_FIND(vm_physmem_ptrs, vm_nphysmem, VM_PHYSSEG_OP_PF, | | 1052 | return VM_PHYSSEG_FIND(vm_physmem_ptrs, vm_nphysmem, VM_PHYSSEG_OP_PF, |
1059 | pframe, NULL, offp); | | 1053 | pframe, NULL, offp); |
1060 | } | | 1054 | } |
1061 | | | 1055 | |
1062 | #ifdef XIP | | | |
1063 | int | | 1056 | int |
1064 | vm_physseg_find_device(paddr_t pframe, int *offp) | | 1057 | vm_physseg_find_device(paddr_t pframe, int *offp) |
1065 | { | | 1058 | { |
1066 | | | 1059 | |
1067 | return VM_PHYSSEG_FIND(vm_physdev_ptrs, vm_nphysdev, VM_PHYSSEG_OP_PF, | | 1060 | return VM_PHYSSEG_FIND(vm_physdev_ptrs, vm_nphysdev, VM_PHYSSEG_OP_PF, |
1068 | pframe, NULL, offp); | | 1061 | pframe, NULL, offp); |
1069 | } | | 1062 | } |
1070 | #endif | | | |
1071 | | | 1063 | |
1072 | #if VM_PHYSSEG_MAX == 1 | | 1064 | #if VM_PHYSSEG_MAX == 1 |
1073 | static inline int | | 1065 | static inline int |
1074 | vm_physseg_find_contig(struct vm_physseg **segs, int nsegs, int op, | | 1066 | vm_physseg_find_contig(struct vm_physseg **segs, int nsegs, int op, |
1075 | paddr_t pframe, const struct vm_page *pg, int *offp) | | 1067 | paddr_t pframe, const struct vm_page *pg, int *offp) |
1076 | { | | 1068 | { |
1077 | | | 1069 | |
1078 | /* 'contig' case */ | | 1070 | /* 'contig' case */ |
1079 | if (nsegs == 0) | | 1071 | if (nsegs == 0) |
1080 | return(-1); | | 1072 | return(-1); |
1081 | if (vm_physseg_within_p(segs[0], op, pframe, pg, offp)) { | | 1073 | if (vm_physseg_within_p(segs[0], op, pframe, pg, offp)) { |
1082 | return(0); | | 1074 | return(0); |
1083 | } | | 1075 | } |
| @@ -1191,31 +1183,29 @@ vm_physseg_lt_p(struct vm_physseg *seg, | | | @@ -1191,31 +1183,29 @@ vm_physseg_lt_p(struct vm_physseg *seg, |
1191 | | | 1183 | |
1192 | /* | | 1184 | /* |
1193 | * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages | | 1185 | * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages |
1194 | * back from an I/O mapping (ugh!). used in some MD code as well. | | 1186 | * back from an I/O mapping (ugh!). used in some MD code as well. |
1195 | */ | | 1187 | */ |
1196 | | | 1188 | |
1197 | struct vm_page * | | 1189 | struct vm_page * |
1198 | uvm_phys_to_vm_page(paddr_t pa) | | 1190 | uvm_phys_to_vm_page(paddr_t pa) |
1199 | { | | 1191 | { |
1200 | paddr_t pf = atop(pa); | | 1192 | paddr_t pf = atop(pa); |
1201 | int off; | | 1193 | int off; |
1202 | int psi; | | 1194 | int psi; |
1203 | | | 1195 | |
1204 | #ifdef XIP | | | |
1205 | psi = vm_physseg_find_device(pf, &off); | | 1196 | psi = vm_physseg_find_device(pf, &off); |
1206 | if (psi != -1) | | 1197 | if (psi != -1) |
1207 | return(&vm_physdev_ptrs[psi]->pgs[off]); | | 1198 | return(&vm_physdev_ptrs[psi]->pgs[off]); |
1208 | #endif | | | |
1209 | psi = vm_physseg_find(pf, &off); | | 1199 | psi = vm_physseg_find(pf, &off); |
1210 | if (psi != -1) | | 1200 | if (psi != -1) |
1211 | return(&vm_physmem_ptrs[psi]->pgs[off]); | | 1201 | return(&vm_physmem_ptrs[psi]->pgs[off]); |
1212 | return(NULL); | | 1202 | return(NULL); |
1213 | } | | 1203 | } |
1214 | | | 1204 | |
1215 | paddr_t | | 1205 | paddr_t |
1216 | uvm_vm_page_to_phys(const struct vm_page *pg) | | 1206 | uvm_vm_page_to_phys(const struct vm_page *pg) |
1217 | { | | 1207 | { |
1218 | | | 1208 | |
1219 | return pg->phys_addr; | | 1209 | return pg->phys_addr; |
1220 | } | | 1210 | } |
1221 | | | 1211 | |
| @@ -2211,29 +2201,27 @@ uvm_pagecopy(struct vm_page *src, struct | | | @@ -2211,29 +2201,27 @@ uvm_pagecopy(struct vm_page *src, struct |
2211 | dst->flags &= ~PG_CLEAN; | | 2201 | dst->flags &= ~PG_CLEAN; |
2212 | pmap_copy_page(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst)); | | 2202 | pmap_copy_page(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst)); |
2213 | } | | 2203 | } |
2214 | | | 2204 | |
2215 | /* | | 2205 | /* |
2216 | * uvm_pageismanaged: test it see that a page (specified by PA) is managed. | | 2206 | * uvm_pageismanaged: test it see that a page (specified by PA) is managed. |
2217 | */ | | 2207 | */ |
2218 | | | 2208 | |
2219 | bool | | 2209 | bool |
2220 | uvm_pageismanaged(paddr_t pa) | | 2210 | uvm_pageismanaged(paddr_t pa) |
2221 | { | | 2211 | { |
2222 | | | 2212 | |
2223 | return | | 2213 | return |
2224 | #ifdef XIP | | | |
2225 | (vm_physseg_find_device(atop(pa), NULL) != -1) || | | 2214 | (vm_physseg_find_device(atop(pa), NULL) != -1) || |
2226 | #endif | | | |
2227 | (vm_physseg_find(atop(pa), NULL) != -1); | | 2215 | (vm_physseg_find(atop(pa), NULL) != -1); |
2228 | } | | 2216 | } |
2229 | | | 2217 | |
2230 | /* | | 2218 | /* |
2231 | * uvm_page_lookup_freelist: look up the free list for the specified page | | 2219 | * uvm_page_lookup_freelist: look up the free list for the specified page |
2232 | */ | | 2220 | */ |
2233 | | | 2221 | |
2234 | int | | 2222 | int |
2235 | uvm_page_lookup_freelist(struct vm_page *pg) | | 2223 | uvm_page_lookup_freelist(struct vm_page *pg) |
2236 | { | | 2224 | { |
2237 | int lcv; | | 2225 | int lcv; |
2238 | | | 2226 | |
2239 | lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL); | | 2227 | lcv = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), NULL); |