Index: arch/ppc32/src/asm.S
===================================================================
--- arch/ppc32/src/asm.S	(revision 281224aeb3d8da7b9f59d258df830ad80784c70c)
+++ arch/ppc32/src/asm.S	(revision ffdfcf05871253ab133f8a65b0b3eb27581cc829)
@@ -36,4 +36,8 @@
 .global memsetb
 .global memcpy
+.global memcpy_from_uspace
+.global memcpy_to_uspace
+.global memcpy_from_uspace_failover_address
+.global memcpy_to_uspace_failover_address
 
 userspace_asm:
@@ -234,4 +238,7 @@
 
 memcpy:
+memcpy_from_uspace:
+memcpy_to_uspace:
+
 	srwi. r7, r5, 3
 	addi r6, r3, -4
@@ -294,2 +301,6 @@
 	mtctr r7
 	b 1b
+
+memcpy_from_uspace_failover_address:
+memcpy_to_uspace_failover_address:
+	b memcpy_from_uspace_failover_address
Index: arch/ppc32/src/mm/tlb.c
===================================================================
--- arch/ppc32/src/mm/tlb.c	(revision 281224aeb3d8da7b9f59d258df830ad80784c70c)
+++ arch/ppc32/src/mm/tlb.c	(revision ffdfcf05871253ab133f8a65b0b3eb27581cc829)
@@ -69,8 +69,10 @@
  *
  * @param badvaddr Faulting virtual address.
+ * @param istate Pointer to interrupted state.
+ * @param pfrc Pointer to variable where as_page_fault() return code will be stored.
  * @return         PTE on success, NULL otherwise.
  *
  */
-static pte_t *find_mapping_and_check(__address badvaddr)
+static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfcr)
 {
 	/*
@@ -85,4 +87,6 @@
 		return pte;
 	} else {
+		int rc;
+	
 		/*
 		 * Mapping not found in page tables.
@@ -90,5 +94,6 @@
 		 */
 		page_table_unlock(AS, true);
-		if (as_page_fault(badvaddr)) {
+		switch (rc = as_page_fault(badvaddr, istate)) {
+		case AS_PF_OK:
 			/*
 			 * The higher-level page fault handler succeeded,
@@ -99,10 +104,20 @@
 			ASSERT((pte) && (pte->p));
 			return pte;
-		} else {
+			break;
+		case AS_PF_DEFER:
+			page_table_lock(AS, true);
+			*pfcr = rc;
+			return NULL;
+			break;
+		case AS_PF_FAULT:
 			page_table_lock(AS, true);
 			printf("Page fault.\n");
+			*pfcr = rc;
 			return NULL;
-		}
-		
+			break;
+		default:
+			panic("unexpected rc (%d)\n", rc);
+			break;
+		}	
 	}
 }
@@ -140,4 +155,5 @@
 	__u32 hash;
 	__u32 i;
+	int pfcr;
 	
 	if (data) {
@@ -155,7 +171,22 @@
 	page_table_lock(AS, true);
 	
-	pte = find_mapping_and_check(badvaddr);
-	if (!pte)
-		goto fail;
+	pte = find_mapping_and_check(badvaddr, istate, &pfcr);
+	if (!pte) {
+		switch (pfcr) {
+		case AS_PF_FAULT:
+			goto fail;
+			break;
+		case AS_PF_DEFER:
+			/*
+		 	 * The page fault came during copy_from_uspace()
+			 * or copy_to_uspace().
+			 */
+			page_table_unlock(AS, true);
+			return;
+		default:
+			panic("Unexpected pfrc (%d)\n", pfcr);
+			break;
+		}
+	}
 
 	/* Record access to PTE */
