Skip to content

Commit 1429d46

Browse files
Zoltan KissDavid Vrabel
authored andcommitted
xen/grant-table: Refactor gnttab_[un]map_refs to avoid m2p_override
The grant mapping API does m2p_override unnecessarily: only gntdev needs it, for blkback and future netback patches it just cause a lock contention, as those pages never go to userspace. Therefore this series does the following: - the bulk of the original function (everything after the mapping hypercall) is moved to arch-dependent set/clear_foreign_p2m_mapping - the "if (xen_feature(XENFEAT_auto_translated_physmap))" branch goes to ARM - therefore the ARM function could be much smaller, the m2p_override stubs could be also removed - on x86 the set_phys_to_machine calls were moved up to this new funcion from m2p_override functions - and m2p_override functions are only called when there is a kmap_ops param It also removes a stray space from arch/x86/include/asm/xen/page.h. Signed-off-by: Zoltan Kiss <[email protected]> Suggested-by: Anthony Liguori <[email protected]> Suggested-by: David Vrabel <[email protected]> Suggested-by: Stefano Stabellini <[email protected]> Signed-off-by: David Vrabel <[email protected]> Signed-off-by: Stefano Stabellini <[email protected]>
1 parent 395edbb commit 1429d46

File tree

5 files changed

+156
-96
lines changed

5 files changed

+156
-96
lines changed

arch/arm/include/asm/xen/page.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,13 @@ static inline pte_t *lookup_address(unsigned long address, unsigned int *level)
9797
return NULL;
9898
}
9999

100-
static inline int m2p_add_override(unsigned long mfn, struct page *page,
101-
struct gnttab_map_grant_ref *kmap_op)
102-
{
103-
return 0;
104-
}
100+
extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
101+
struct gnttab_map_grant_ref *kmap_ops,
102+
struct page **pages, unsigned int count);
105103

106-
static inline int m2p_remove_override(struct page *page, bool clear_pte)
107-
{
108-
return 0;
109-
}
104+
extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
105+
struct gnttab_map_grant_ref *kmap_ops,
106+
struct page **pages, unsigned int count);
110107

111108
bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
112109
bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn,

arch/arm/xen/p2m.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,38 @@ unsigned long __mfn_to_pfn(unsigned long mfn)
146146
}
147147
EXPORT_SYMBOL_GPL(__mfn_to_pfn);
148148

149+
int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
150+
struct gnttab_map_grant_ref *kmap_ops,
151+
struct page **pages, unsigned int count)
152+
{
153+
int i;
154+
155+
for (i = 0; i < count; i++) {
156+
if (map_ops[i].status)
157+
continue;
158+
set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT,
159+
map_ops[i].dev_bus_addr >> PAGE_SHIFT);
160+
}
161+
162+
return 0;
163+
}
164+
EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping);
165+
166+
int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
167+
struct gnttab_map_grant_ref *kmap_ops,
168+
struct page **pages, unsigned int count)
169+
{
170+
int i;
171+
172+
for (i = 0; i < count; i++) {
173+
set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT,
174+
INVALID_P2M_ENTRY);
175+
}
176+
177+
return 0;
178+
}
179+
EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping);
180+
149181
bool __set_phys_to_machine_multi(unsigned long pfn,
150182
unsigned long mfn, unsigned long nr_pages)
151183
{

arch/x86/include/asm/xen/page.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,17 @@ extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
4949
extern unsigned long set_phys_range_identity(unsigned long pfn_s,
5050
unsigned long pfn_e);
5151

52+
extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
53+
struct gnttab_map_grant_ref *kmap_ops,
54+
struct page **pages, unsigned int count);
5255
extern int m2p_add_override(unsigned long mfn, struct page *page,
5356
struct gnttab_map_grant_ref *kmap_op);
57+
extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
58+
struct gnttab_map_grant_ref *kmap_ops,
59+
struct page **pages, unsigned int count);
5460
extern int m2p_remove_override(struct page *page,
55-
struct gnttab_map_grant_ref *kmap_op);
61+
struct gnttab_map_grant_ref *kmap_op,
62+
unsigned long mfn);
5663
extern struct page *m2p_find_override(unsigned long mfn);
5764
extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
5865

@@ -121,7 +128,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
121128
pfn = m2p_find_override_pfn(mfn, ~0);
122129
}
123130

124-
/*
131+
/*
125132
* pfn is ~0 if there are no entries in the m2p for mfn or if the
126133
* entry doesn't map back to the mfn and m2p_override doesn't have a
127134
* valid entry for it.

arch/x86/xen/p2m.c

Lines changed: 106 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,65 @@ static unsigned long mfn_hash(unsigned long mfn)
881881
return hash_long(mfn, M2P_OVERRIDE_HASH_SHIFT);
882882
}
883883

884+
int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
885+
struct gnttab_map_grant_ref *kmap_ops,
886+
struct page **pages, unsigned int count)
887+
{
888+
int i, ret = 0;
889+
bool lazy = false;
890+
pte_t *pte;
891+
892+
if (xen_feature(XENFEAT_auto_translated_physmap))
893+
return 0;
894+
895+
if (kmap_ops &&
896+
!in_interrupt() &&
897+
paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
898+
arch_enter_lazy_mmu_mode();
899+
lazy = true;
900+
}
901+
902+
for (i = 0; i < count; i++) {
903+
unsigned long mfn, pfn;
904+
905+
/* Do not add to override if the map failed. */
906+
if (map_ops[i].status)
907+
continue;
908+
909+
if (map_ops[i].flags & GNTMAP_contains_pte) {
910+
pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
911+
(map_ops[i].host_addr & ~PAGE_MASK));
912+
mfn = pte_mfn(*pte);
913+
} else {
914+
mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
915+
}
916+
pfn = page_to_pfn(pages[i]);
917+
918+
WARN_ON(PagePrivate(pages[i]));
919+
SetPagePrivate(pages[i]);
920+
set_page_private(pages[i], mfn);
921+
pages[i]->index = pfn_to_mfn(pfn);
922+
923+
if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) {
924+
ret = -ENOMEM;
925+
goto out;
926+
}
927+
928+
if (kmap_ops) {
929+
ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]);
930+
if (ret)
931+
goto out;
932+
}
933+
}
934+
935+
out:
936+
if (lazy)
937+
arch_leave_lazy_mmu_mode();
938+
939+
return ret;
940+
}
941+
EXPORT_SYMBOL_GPL(set_foreign_p2m_mapping);
942+
884943
/* Add an MFN override for a particular page */
885944
int m2p_add_override(unsigned long mfn, struct page *page,
886945
struct gnttab_map_grant_ref *kmap_op)
@@ -899,13 +958,6 @@ int m2p_add_override(unsigned long mfn, struct page *page,
899958
"m2p_add_override: pfn %lx not mapped", pfn))
900959
return -EINVAL;
901960
}
902-
WARN_ON(PagePrivate(page));
903-
SetPagePrivate(page);
904-
set_page_private(page, mfn);
905-
page->index = pfn_to_mfn(pfn);
906-
907-
if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
908-
return -ENOMEM;
909961

910962
if (kmap_op != NULL) {
911963
if (!PageHighMem(page)) {
@@ -943,20 +995,62 @@ int m2p_add_override(unsigned long mfn, struct page *page,
943995
return 0;
944996
}
945997
EXPORT_SYMBOL_GPL(m2p_add_override);
998+
999+
int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
1000+
struct gnttab_map_grant_ref *kmap_ops,
1001+
struct page **pages, unsigned int count)
1002+
{
1003+
int i, ret = 0;
1004+
bool lazy = false;
1005+
1006+
if (xen_feature(XENFEAT_auto_translated_physmap))
1007+
return 0;
1008+
1009+
if (kmap_ops &&
1010+
!in_interrupt() &&
1011+
paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
1012+
arch_enter_lazy_mmu_mode();
1013+
lazy = true;
1014+
}
1015+
1016+
for (i = 0; i < count; i++) {
1017+
unsigned long mfn = get_phys_to_machine(page_to_pfn(pages[i]));
1018+
unsigned long pfn = page_to_pfn(pages[i]);
1019+
1020+
if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) {
1021+
ret = -EINVAL;
1022+
goto out;
1023+
}
1024+
1025+
set_page_private(pages[i], INVALID_P2M_ENTRY);
1026+
WARN_ON(!PagePrivate(pages[i]));
1027+
ClearPagePrivate(pages[i]);
1028+
set_phys_to_machine(pfn, pages[i]->index);
1029+
1030+
if (kmap_ops)
1031+
ret = m2p_remove_override(pages[i], &kmap_ops[i], mfn);
1032+
if (ret)
1033+
goto out;
1034+
}
1035+
1036+
out:
1037+
if (lazy)
1038+
arch_leave_lazy_mmu_mode();
1039+
return ret;
1040+
}
1041+
EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping);
1042+
9461043
int m2p_remove_override(struct page *page,
947-
struct gnttab_map_grant_ref *kmap_op)
1044+
struct gnttab_map_grant_ref *kmap_op,
1045+
unsigned long mfn)
9481046
{
9491047
unsigned long flags;
950-
unsigned long mfn;
9511048
unsigned long pfn;
9521049
unsigned long uninitialized_var(address);
9531050
unsigned level;
9541051
pte_t *ptep = NULL;
9551052

9561053
pfn = page_to_pfn(page);
957-
mfn = get_phys_to_machine(pfn);
958-
if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
959-
return -EINVAL;
9601054

9611055
if (!PageHighMem(page)) {
9621056
address = (unsigned long)__va(pfn << PAGE_SHIFT);
@@ -970,10 +1064,7 @@ int m2p_remove_override(struct page *page,
9701064
spin_lock_irqsave(&m2p_override_lock, flags);
9711065
list_del(&page->lru);
9721066
spin_unlock_irqrestore(&m2p_override_lock, flags);
973-
WARN_ON(!PagePrivate(page));
974-
ClearPagePrivate(page);
9751067

976-
set_phys_to_machine(pfn, page->index);
9771068
if (kmap_op != NULL) {
9781069
if (!PageHighMem(page)) {
9791070
struct multicall_space mcs;

drivers/xen/grant-table.c

Lines changed: 3 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -933,9 +933,6 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
933933
struct page **pages, unsigned int count)
934934
{
935935
int i, ret;
936-
bool lazy = false;
937-
pte_t *pte;
938-
unsigned long mfn;
939936

940937
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
941938
if (ret)
@@ -947,85 +944,21 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
947944
gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i,
948945
&map_ops[i].status, __func__);
949946

950-
/* this is basically a nop on x86 */
951-
if (xen_feature(XENFEAT_auto_translated_physmap)) {
952-
for (i = 0; i < count; i++) {
953-
if (map_ops[i].status)
954-
continue;
955-
set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT,
956-
map_ops[i].dev_bus_addr >> PAGE_SHIFT);
957-
}
958-
return ret;
959-
}
960-
961-
if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
962-
arch_enter_lazy_mmu_mode();
963-
lazy = true;
964-
}
965-
966-
for (i = 0; i < count; i++) {
967-
/* Do not add to override if the map failed. */
968-
if (map_ops[i].status)
969-
continue;
970-
971-
if (map_ops[i].flags & GNTMAP_contains_pte) {
972-
pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
973-
(map_ops[i].host_addr & ~PAGE_MASK));
974-
mfn = pte_mfn(*pte);
975-
} else {
976-
mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
977-
}
978-
ret = m2p_add_override(mfn, pages[i], kmap_ops ?
979-
&kmap_ops[i] : NULL);
980-
if (ret)
981-
goto out;
982-
}
983-
984-
out:
985-
if (lazy)
986-
arch_leave_lazy_mmu_mode();
987-
988-
return ret;
947+
return set_foreign_p2m_mapping(map_ops, kmap_ops, pages, count);
989948
}
990949
EXPORT_SYMBOL_GPL(gnttab_map_refs);
991950

992951
int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
993952
struct gnttab_map_grant_ref *kmap_ops,
994953
struct page **pages, unsigned int count)
995954
{
996-
int i, ret;
997-
bool lazy = false;
955+
int ret;
998956

999957
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
1000958
if (ret)
1001959
return ret;
1002960

1003-
/* this is basically a nop on x86 */
1004-
if (xen_feature(XENFEAT_auto_translated_physmap)) {
1005-
for (i = 0; i < count; i++) {
1006-
set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT,
1007-
INVALID_P2M_ENTRY);
1008-
}
1009-
return ret;
1010-
}
1011-
1012-
if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
1013-
arch_enter_lazy_mmu_mode();
1014-
lazy = true;
1015-
}
1016-
1017-
for (i = 0; i < count; i++) {
1018-
ret = m2p_remove_override(pages[i], kmap_ops ?
1019-
&kmap_ops[i] : NULL);
1020-
if (ret)
1021-
goto out;
1022-
}
1023-
1024-
out:
1025-
if (lazy)
1026-
arch_leave_lazy_mmu_mode();
1027-
1028-
return ret;
961+
return clear_foreign_p2m_mapping(unmap_ops, kmap_ops, pages, count);
1029962
}
1030963
EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
1031964

0 commit comments

Comments
 (0)