5 #include <minix/callnr.h>
6 #include <minix/type.h>
7 #include <minix/config.h>
8 #include <minix/const.h>
9 #include <minix/sysutil.h>
10 #include <minix/syslib.h>
11 #include <minix/debug.h>
12 #include <minix/bitmap.h>
13 #include <minix/hash.h>
22 #include <sys/param.h>
29 #include "sanitycheck.h"
32 struct phys_block
*pb_new(phys_bytes phys
)
34 struct phys_block
*newpb
;
36 if(!SLABALLOC(newpb
)) {
37 printf("vm: pb_new: couldn't allocate phys block\n");
42 assert(!(phys
% VM_PAGE_SIZE
));
47 newpb
->firstregion
= NULL
;
54 void pb_free(struct phys_block
*pb
)
56 if(pb
->phys
!= MAP_NONE
)
57 free_mem(ABS2CLICK(pb
->phys
), 1);
61 void pb_link(struct phys_region
*newphysr
, struct phys_block
*newpb
,
62 vir_bytes offset
, struct vir_region
*parent
)
65 newphysr
->offset
= offset
;
67 newphysr
->parent
= parent
;
68 newphysr
->next_ph_list
= newpb
->firstregion
;
69 newpb
->firstregion
= newphysr
;);
73 struct phys_region
*pb_reference(struct phys_block
*newpb
,
74 vir_bytes offset
, struct vir_region
*region
, mem_type_t
*memtype
)
76 struct phys_region
*newphysr
;
78 if(!SLABALLOC(newphysr
)) {
79 printf("vm: pb_reference: couldn't allocate phys region\n");
83 newphysr
->memtype
= memtype
;
85 /* New physical region. */
86 pb_link(newphysr
, newpb
, offset
, region
);
88 physblock_set(region
, offset
, newphysr
);
93 /*===========================================================================*
95 *===========================================================================*/
96 void pb_unreferenced(struct vir_region
*region
, struct phys_region
*pr
, int rm
)
98 struct phys_block
*pb
;
101 assert(pb
->refcount
> 0);
102 USE(pb
, pb
->refcount
--;);
103 /* assert(pb->refcount >= 0); */ /* always true */
105 if(pb
->firstregion
== pr
) {
106 USE(pb
, pb
->firstregion
= pr
->next_ph_list
;);
108 struct phys_region
*others
;
110 for(others
= pb
->firstregion
; others
;
111 others
= others
->next_ph_list
) {
112 assert(others
->ph
== pb
);
113 if(others
->next_ph_list
== pr
) {
114 USE(others
, others
->next_ph_list
= pr
->next_ph_list
;);
119 assert(others
); /* Otherwise, wasn't on the list. */
122 if(pb
->refcount
== 0) {
123 assert(!pb
->firstregion
);
125 if((r
= pr
->memtype
->ev_unreference(pr
)) != OK
)
126 panic("unref failed, %d", r
);
133 if(rm
) physblock_set(region
, pr
->offset
, NULL
);
136 int mem_cow(struct vir_region
*region
,
137 struct phys_region
*ph
, phys_bytes new_page_cl
, phys_bytes new_page
)
139 struct phys_block
*pb
;
141 if(new_page
== MAP_NONE
) {
143 allocflags
= vrallocflags(region
->flags
);
145 if((new_page_cl
= alloc_mem(1, allocflags
)) == NO_MEM
)
148 new_page
= CLICK2ABS(new_page_cl
);
151 assert(ph
->ph
->phys
!= MAP_NONE
);
153 if(sys_abscopy(ph
->ph
->phys
, new_page
, VM_PAGE_SIZE
) != OK
) {
154 panic("VM: abscopy failed\n");
158 if(!(pb
= pb_new(new_page
))) {
159 free_mem(new_page_cl
, 1);
163 pb_unreferenced(region
, ph
, 0);
164 pb_link(ph
, pb
, ph
->offset
, region
);
165 ph
->memtype
= &mem_type_anon
;