Skip to contentSkip to conversation

linux/x86: batch hypercalls when pinning address spaces

PATCH New Jan Beulich 1 participant 1 message Mar 26, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 linux/x86: batch hypercalls when pinning address spaces

arch/i386/mm/pgtable-xen.c +37 -17
Index: head-2007-03-19/arch/i386/mm/pgtable-xen.c
===================================================================
@@ -574,10 +574,13 @@ static void _pin_lock(struct mm_struct *
 	}
 }
 
-static inline void pgd_walk_set_prot(struct page *page, pgprot_t flags)
+#define PIN_BATCH 4
+static DEFINE_PER_CPU(multicall_entry_t[PIN_BATCH], pb_mcl);
+
+static inline unsigned int pgd_walk_set_prot(struct page *page, pgprot_t flags,
+                                             unsigned int cpu, unsigned seq)
 {
 	unsigned long pfn = page_to_pfn(page);
-	int rc;
 
 	if (PageHighMem(page)) {
 		if (pgprot_val(flags) & _PAGE_RW)
@@ -585,12 +588,18 @@ static inline void pgd_walk_set_prot(str
 		else
 			set_bit(PG_pinned, &page->flags);
 	} else {
-		rc = HYPERVISOR_update_va_mapping(
-			(unsigned long)__va(pfn << PAGE_SHIFT),
-			pfn_pte(pfn, flags), 0);
-		if (rc)
-			BUG();
+		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+				(unsigned long)__va(pfn << PAGE_SHIFT),
+				pfn_pte(pfn, flags), 0);
+		if (unlikely(++seq == PIN_BATCH)) {
+			if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+		                                                PIN_BATCH, NULL)))
+				BUG();
+			seq = 0;
+		}
 	}
+
+	return seq;
 }
 
 static void pgd_walk(pgd_t *pgd_base, pgprot_t flags)
@@ -598,37 +607,48 @@ static void pgd_walk(pgd_t *pgd_base, pg
 	pgd_t *pgd = pgd_base;
 	pud_t *pud;
 	pmd_t *pmd;
-	int    g, u, m, rc;
+	int    g, u, m;
+	unsigned int cpu, seq;
 
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return;
 
-	for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
+	cpu = get_cpu();
+
+	for (g = 0, seq = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
 		if (pgd_none(*pgd))
 			continue;
 		pud = pud_offset(pgd, 0);
 		if (PTRS_PER_PUD > 1) /* not folded */
-			pgd_walk_set_prot(virt_to_page(pud),flags);
+			seq = pgd_walk_set_prot(virt_to_page(pud),flags,cpu,seq);
 		for (u = 0; u < PTRS_PER_PUD; u++, pud++) {
 			if (pud_none(*pud))
 				continue;
 			pmd = pmd_offset(pud, 0);
 			if (PTRS_PER_PMD > 1) /* not folded */
-				pgd_walk_set_prot(virt_to_page(pmd),flags);
+				seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq);
 			for (m = 0; m < PTRS_PER_PMD; m++, pmd++) {
 				if (pmd_none(*pmd))
 					continue;
-				pgd_walk_set_prot(pmd_page(*pmd),flags);
+				seq = pgd_walk_set_prot(pmd_page(*pmd),flags,cpu,seq);
 			}
 		}
 	}
 
-	rc = HYPERVISOR_update_va_mapping(
-		(unsigned long)pgd_base,
-		pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
-		UVMF_TLB_FLUSH);
-	if (rc)
+	if (likely(seq != 0)) {
+		MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq,
+			(unsigned long)pgd_base,
+			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+			UVMF_TLB_FLUSH);
+		if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu),
+		                                        seq + 1, NULL)))
+			BUG();
+	} else if(HYPERVISOR_update_va_mapping((unsigned long)pgd_base,
+			pfn_pte(virt_to_phys(pgd_base)>>PAGE_SHIFT, flags),
+			UVMF_TLB_FLUSH))
 		BUG();
+
+	put_cpu();
 }
 
 static void __pgd_pin(pgd_t *pgd)
arch/x86_64/mm/pageattr-xen.c +41 -30

126 lines not on this page · raw message