summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--serverboot/wiring.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/serverboot/wiring.c b/serverboot/wiring.c
index ddcbd373..585a3075 100644
--- a/serverboot/wiring.c
+++ b/serverboot/wiring.c
@@ -1,25 +1,25 @@
-/*
+/*
* Mach Operating System
* Copyright (c) 1991 Carnegie Mellon University
* All Rights Reserved.
- *
+ *
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
- *
+ *
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
+ *
* Carnegie Mellon requests users of this software to return to
- *
+ *
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
- *
+ *
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
@@ -107,7 +107,31 @@ wire_all_memory()
if (MACH_PORT_VALID(object))
(void) mach_port_deallocate(this_task, object);
if (protection != VM_PROT_NONE)
- wire_memory(address, size, protection);
+ {
+ /* The VM system cannot cope with a COW fault on another
+ unrelated virtual copy happening later when we have
+ wired down the original page. So we must touch all our
+ pages before wiring to make sure that only we will ever
+ use them. */
+ void *page;
+ if (!(protection & VM_PROT_WRITE))
+ {
+ kr = vm_protect(this_task, address, size,
+ 0, max_protection);
+ }
+ for (page = (void *) address;
+ page < (void *) (address + size);
+ page += vm_page_size)
+ *(volatile int *) page = *(int *) page;
+
+ wire_memory(address, size, protection);
+
+ if (!(protection & VM_PROT_WRITE))
+ {
+ kr = vm_protect(this_task, address, size,
+ 0, protection);
+ }
+ }
address += size;
}
}
@@ -149,4 +173,3 @@ __vm_allocate (task, address, size, anywhere)
{
return vm_allocate (task, address, size, anywhere);
}
-