diff options
40 files changed, 916 insertions, 249 deletions
diff --git a/arch/ia64/include/asm/xen/interface.h b/arch/ia64/include/asm/xen/interface.h index 09d5f7fd9db1..3d52a5bbd857 100644 --- a/arch/ia64/include/asm/xen/interface.h +++ b/arch/ia64/include/asm/xen/interface.h | |||
@@ -67,6 +67,10 @@ | |||
67 | #define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) | 67 | #define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) |
68 | 68 | ||
69 | #ifndef __ASSEMBLY__ | 69 | #ifndef __ASSEMBLY__ |
70 | /* Explicitly size integers that represent pfns in the public interface | ||
71 | * with Xen so that we could have one ABI that works for 32 and 64 bit | ||
72 | * guests. */ | ||
73 | typedef unsigned long xen_pfn_t; | ||
70 | /* Guest handles for primitive C types. */ | 74 | /* Guest handles for primitive C types. */ |
71 | __DEFINE_GUEST_HANDLE(uchar, unsigned char); | 75 | __DEFINE_GUEST_HANDLE(uchar, unsigned char); |
72 | __DEFINE_GUEST_HANDLE(uint, unsigned int); | 76 | __DEFINE_GUEST_HANDLE(uint, unsigned int); |
@@ -79,7 +83,6 @@ DEFINE_GUEST_HANDLE(void); | |||
79 | DEFINE_GUEST_HANDLE(uint64_t); | 83 | DEFINE_GUEST_HANDLE(uint64_t); |
80 | DEFINE_GUEST_HANDLE(uint32_t); | 84 | DEFINE_GUEST_HANDLE(uint32_t); |
81 | 85 | ||
82 | typedef unsigned long xen_pfn_t; | ||
83 | DEFINE_GUEST_HANDLE(xen_pfn_t); | 86 | DEFINE_GUEST_HANDLE(xen_pfn_t); |
84 | #define PRI_xen_pfn "lx" | 87 | #define PRI_xen_pfn "lx" |
85 | #endif | 88 | #endif |
@@ -265,6 +268,8 @@ typedef struct xen_callback xen_callback_t; | |||
265 | 268 | ||
266 | #endif /* !__ASSEMBLY__ */ | 269 | #endif /* !__ASSEMBLY__ */ |
267 | 270 | ||
271 | #include <asm/pvclock-abi.h> | ||
272 | |||
268 | /* Size of the shared_info area (this is not related to page size). */ | 273 | /* Size of the shared_info area (this is not related to page size). */ |
269 | #define XSI_SHIFT 14 | 274 | #define XSI_SHIFT 14 |
270 | #define XSI_SIZE (1 << XSI_SHIFT) | 275 | #define XSI_SIZE (1 << XSI_SHIFT) |
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h index cbf0c9d50b92..555f94d3637b 100644 --- a/arch/x86/include/asm/xen/interface.h +++ b/arch/x86/include/asm/xen/interface.h | |||
@@ -47,6 +47,10 @@ | |||
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifndef __ASSEMBLY__ | 49 | #ifndef __ASSEMBLY__ |
50 | /* Explicitly size integers that represent pfns in the public interface | ||
51 | * with Xen so that on ARM we can have one ABI that works for 32 and 64 | ||
52 | * bit guests. */ | ||
53 | typedef unsigned long xen_pfn_t; | ||
50 | /* Guest handles for primitive C types. */ | 54 | /* Guest handles for primitive C types. */ |
51 | __DEFINE_GUEST_HANDLE(uchar, unsigned char); | 55 | __DEFINE_GUEST_HANDLE(uchar, unsigned char); |
52 | __DEFINE_GUEST_HANDLE(uint, unsigned int); | 56 | __DEFINE_GUEST_HANDLE(uint, unsigned int); |
@@ -57,6 +61,7 @@ DEFINE_GUEST_HANDLE(long); | |||
57 | DEFINE_GUEST_HANDLE(void); | 61 | DEFINE_GUEST_HANDLE(void); |
58 | DEFINE_GUEST_HANDLE(uint64_t); | 62 | DEFINE_GUEST_HANDLE(uint64_t); |
59 | DEFINE_GUEST_HANDLE(uint32_t); | 63 | DEFINE_GUEST_HANDLE(uint32_t); |
64 | DEFINE_GUEST_HANDLE(xen_pfn_t); | ||
60 | #endif | 65 | #endif |
61 | 66 | ||
62 | #ifndef HYPERVISOR_VIRT_START | 67 | #ifndef HYPERVISOR_VIRT_START |
@@ -121,6 +126,8 @@ struct arch_shared_info { | |||
121 | #include "interface_64.h" | 126 | #include "interface_64.h" |
122 | #endif | 127 | #endif |
123 | 128 | ||
129 | #include <asm/pvclock-abi.h> | ||
130 | |||
124 | #ifndef __ASSEMBLY__ | 131 | #ifndef __ASSEMBLY__ |
125 | /* | 132 | /* |
126 | * The following is all CPU context. Note that the fpu_ctxt block is filled | 133 | * The following is all CPU context. Note that the fpu_ctxt block is filled |
diff --git a/arch/x86/include/asm/xen/swiotlb-xen.h b/arch/x86/include/asm/xen/swiotlb-xen.h index 1be1ab7d6a41..ee52fcac6f72 100644 --- a/arch/x86/include/asm/xen/swiotlb-xen.h +++ b/arch/x86/include/asm/xen/swiotlb-xen.h | |||
@@ -5,10 +5,12 @@ | |||
5 | extern int xen_swiotlb; | 5 | extern int xen_swiotlb; |
6 | extern int __init pci_xen_swiotlb_detect(void); | 6 | extern int __init pci_xen_swiotlb_detect(void); |
7 | extern void __init pci_xen_swiotlb_init(void); | 7 | extern void __init pci_xen_swiotlb_init(void); |
8 | extern int pci_xen_swiotlb_init_late(void); | ||
8 | #else | 9 | #else |
9 | #define xen_swiotlb (0) | 10 | #define xen_swiotlb (0) |
10 | static inline int __init pci_xen_swiotlb_detect(void) { return 0; } | 11 | static inline int __init pci_xen_swiotlb_detect(void) { return 0; } |
11 | static inline void __init pci_xen_swiotlb_init(void) { } | 12 | static inline void __init pci_xen_swiotlb_init(void) { } |
13 | static inline int pci_xen_swiotlb_init_late(void) { return -ENXIO; } | ||
12 | #endif | 14 | #endif |
13 | 15 | ||
14 | #endif /* _ASM_X86_SWIOTLB_XEN_H */ | 16 | #endif /* _ASM_X86_SWIOTLB_XEN_H */ |
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c index ec57bd3818a4..7005ced5d1ad 100644 --- a/arch/x86/xen/apic.c +++ b/arch/x86/xen/apic.c | |||
@@ -6,8 +6,9 @@ | |||
6 | 6 | ||
7 | #include <xen/xen.h> | 7 | #include <xen/xen.h> |
8 | #include <xen/interface/physdev.h> | 8 | #include <xen/interface/physdev.h> |
9 | #include "xen-ops.h" | ||
9 | 10 | ||
10 | unsigned int xen_io_apic_read(unsigned apic, unsigned reg) | 11 | static unsigned int xen_io_apic_read(unsigned apic, unsigned reg) |
11 | { | 12 | { |
12 | struct physdev_apic apic_op; | 13 | struct physdev_apic apic_op; |
13 | int ret; | 14 | int ret; |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 1fbe75a95f15..2d932c351f91 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -80,6 +80,8 @@ | |||
80 | #include "smp.h" | 80 | #include "smp.h" |
81 | #include "multicalls.h" | 81 | #include "multicalls.h" |
82 | 82 | ||
83 | #include <xen/events.h> | ||
84 | |||
83 | EXPORT_SYMBOL_GPL(hypercall_page); | 85 | EXPORT_SYMBOL_GPL(hypercall_page); |
84 | 86 | ||
85 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | 87 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); |
@@ -1288,7 +1290,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1288 | { | 1290 | { |
1289 | struct physdev_set_iopl set_iopl; | 1291 | struct physdev_set_iopl set_iopl; |
1290 | int rc; | 1292 | int rc; |
1291 | pgd_t *pgd; | ||
1292 | 1293 | ||
1293 | if (!xen_start_info) | 1294 | if (!xen_start_info) |
1294 | return; | 1295 | return; |
@@ -1380,8 +1381,6 @@ asmlinkage void __init xen_start_kernel(void) | |||
1380 | acpi_numa = -1; | 1381 | acpi_numa = -1; |
1381 | #endif | 1382 | #endif |
1382 | 1383 | ||
1383 | pgd = (pgd_t *)xen_start_info->pt_base; | ||
1384 | |||
1385 | /* Don't do the full vcpu_info placement stuff until we have a | 1384 | /* Don't do the full vcpu_info placement stuff until we have a |
1386 | possible map and a non-dummy shared_info. */ | 1385 | possible map and a non-dummy shared_info. */ |
1387 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; | 1386 | per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; |
@@ -1390,7 +1389,7 @@ asmlinkage void __init xen_start_kernel(void) | |||
1390 | early_boot_irqs_disabled = true; | 1389 | early_boot_irqs_disabled = true; |
1391 | 1390 | ||
1392 | xen_raw_console_write("mapping kernel into physical memory\n"); | 1391 | xen_raw_console_write("mapping kernel into physical memory\n"); |
1393 | pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages); | 1392 | xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base, xen_start_info->nr_pages); |
1394 | 1393 | ||
1395 | /* Allocate and initialize top and mid mfn levels for p2m structure */ | 1394 | /* Allocate and initialize top and mid mfn levels for p2m structure */ |
1396 | xen_build_mfn_list_list(); | 1395 | xen_build_mfn_list_list(); |
@@ -1441,11 +1440,19 @@ asmlinkage void __init xen_start_kernel(void) | |||
1441 | const struct dom0_vga_console_info *info = | 1440 | const struct dom0_vga_console_info *info = |
1442 | (void *)((char *)xen_start_info + | 1441 | (void *)((char *)xen_start_info + |
1443 | xen_start_info->console.dom0.info_off); | 1442 | xen_start_info->console.dom0.info_off); |
1443 | struct xen_platform_op op = { | ||
1444 | .cmd = XENPF_firmware_info, | ||
1445 | .interface_version = XENPF_INTERFACE_VERSION, | ||
1446 | .u.firmware_info.type = XEN_FW_KBD_SHIFT_FLAGS, | ||
1447 | }; | ||
1444 | 1448 | ||
1445 | xen_init_vga(info, xen_start_info->console.dom0.info_size); | 1449 | xen_init_vga(info, xen_start_info->console.dom0.info_size); |
1446 | xen_start_info->console.domU.mfn = 0; | 1450 | xen_start_info->console.domU.mfn = 0; |
1447 | xen_start_info->console.domU.evtchn = 0; | 1451 | xen_start_info->console.domU.evtchn = 0; |
1448 | 1452 | ||
1453 | if (HYPERVISOR_dom0_op(&op) == 0) | ||
1454 | boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags; | ||
1455 | |||
1449 | xen_init_apic(); | 1456 | xen_init_apic(); |
1450 | 1457 | ||
1451 | /* Make sure ACS will be enabled */ | 1458 | /* Make sure ACS will be enabled */ |
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 7a769b7526cb..5a16824cc2b3 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -84,6 +84,7 @@ | |||
84 | */ | 84 | */ |
85 | DEFINE_SPINLOCK(xen_reservation_lock); | 85 | DEFINE_SPINLOCK(xen_reservation_lock); |
86 | 86 | ||
87 | #ifdef CONFIG_X86_32 | ||
87 | /* | 88 | /* |
88 | * Identity map, in addition to plain kernel map. This needs to be | 89 | * Identity map, in addition to plain kernel map. This needs to be |
89 | * large enough to allocate page table pages to allocate the rest. | 90 | * large enough to allocate page table pages to allocate the rest. |
@@ -91,7 +92,7 @@ DEFINE_SPINLOCK(xen_reservation_lock); | |||
91 | */ | 92 | */ |
92 | #define LEVEL1_IDENT_ENTRIES (PTRS_PER_PTE * 4) | 93 | #define LEVEL1_IDENT_ENTRIES (PTRS_PER_PTE * 4) |
93 | static RESERVE_BRK_ARRAY(pte_t, level1_ident_pgt, LEVEL1_IDENT_ENTRIES); | 94 | static RESERVE_BRK_ARRAY(pte_t, level1_ident_pgt, LEVEL1_IDENT_ENTRIES); |
94 | 95 | #endif | |
95 | #ifdef CONFIG_X86_64 | 96 | #ifdef CONFIG_X86_64 |
96 | /* l3 pud for userspace vsyscall mapping */ | 97 | /* l3 pud for userspace vsyscall mapping */ |
97 | static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; | 98 | static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; |
@@ -1176,13 +1177,6 @@ static void xen_exit_mmap(struct mm_struct *mm) | |||
1176 | 1177 | ||
1177 | static void xen_post_allocator_init(void); | 1178 | static void xen_post_allocator_init(void); |
1178 | 1179 | ||
1179 | static void __init xen_pagetable_init(void) | ||
1180 | { | ||
1181 | paging_init(); | ||
1182 | xen_setup_shared_info(); | ||
1183 | xen_post_allocator_init(); | ||
1184 | } | ||
1185 | |||
1186 | static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) | 1180 | static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) |
1187 | { | 1181 | { |
1188 | /* reserve the range used */ | 1182 | /* reserve the range used */ |
@@ -1197,6 +1191,87 @@ static __init void xen_mapping_pagetable_reserve(u64 start, u64 end) | |||
1197 | } | 1191 | } |
1198 | } | 1192 | } |
1199 | 1193 | ||
1194 | #ifdef CONFIG_X86_64 | ||
1195 | static void __init xen_cleanhighmap(unsigned long vaddr, | ||
1196 | unsigned long vaddr_end) | ||
1197 | { | ||
1198 | unsigned long kernel_end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1; | ||
1199 | pmd_t *pmd = level2_kernel_pgt + pmd_index(vaddr); | ||
1200 | |||
1201 | /* NOTE: The loop is more greedy than the cleanup_highmap variant. | ||
1202 | * We include the PMD passed in on _both_ boundaries. */ | ||
1203 | for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PAGE_SIZE)); | ||
1204 | pmd++, vaddr += PMD_SIZE) { | ||
1205 | if (pmd_none(*pmd)) | ||
1206 | continue; | ||
1207 | if (vaddr < (unsigned long) _text || vaddr > kernel_end) | ||
1208 | set_pmd(pmd, __pmd(0)); | ||
1209 | } | ||
1210 | /* In case we did something silly, we should crash in this function | ||
1211 | * instead of somewhere later and be confusing. */ | ||
1212 | xen_mc_flush(); | ||
1213 | } | ||
1214 | #endif | ||
1215 | static void __init xen_pagetable_init(void) | ||
1216 | { | ||
1217 | #ifdef CONFIG_X86_64 | ||
1218 | unsigned long size; | ||
1219 | unsigned long addr; | ||
1220 | #endif | ||
1221 | paging_init(); | ||
1222 | xen_setup_shared_info(); | ||
1223 | #ifdef CONFIG_X86_64 | ||
1224 | if (!xen_feature(XENFEAT_auto_translated_physmap)) { | ||
1225 | unsigned long new_mfn_list; | ||
1226 | |||
1227 | size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long)); | ||
1228 | |||
1229 | /* On 32-bit, we get zero so this never gets executed. */ | ||
1230 | new_mfn_list = xen_revector_p2m_tree(); | ||
1231 | if (new_mfn_list && new_mfn_list != xen_start_info->mfn_list) { | ||
1232 | /* using __ka address and sticking INVALID_P2M_ENTRY! */ | ||
1233 | memset((void *)xen_start_info->mfn_list, 0xff, size); | ||
1234 | |||
1235 | /* We should be in __ka space. */ | ||
1236 | BUG_ON(xen_start_info->mfn_list < __START_KERNEL_map); | ||
1237 | addr = xen_start_info->mfn_list; | ||
1238 | /* We roundup to the PMD, which means that if anybody at this stage is | ||
1239 | * using the __ka address of xen_start_info or xen_start_info->shared_info | ||
1240 | * they are in going to crash. Fortunatly we have already revectored | ||
1241 | * in xen_setup_kernel_pagetable and in xen_setup_shared_info. */ | ||
1242 | size = roundup(size, PMD_SIZE); | ||
1243 | xen_cleanhighmap(addr, addr + size); | ||
1244 | |||
1245 | size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long)); | ||
1246 | memblock_free(__pa(xen_start_info->mfn_list), size); | ||
1247 | /* And revector! Bye bye old array */ | ||
1248 | xen_start_info->mfn_list = new_mfn_list; | ||
1249 | } else | ||
1250 | goto skip; | ||
1251 | } | ||
1252 | /* At this stage, cleanup_highmap has already cleaned __ka space | ||
1253 | * from _brk_limit way up to the max_pfn_mapped (which is the end of | ||
1254 | * the ramdisk). We continue on, erasing PMD entries that point to page | ||
1255 | * tables - do note that they are accessible at this stage via __va. | ||
1256 | * For good measure we also round up to the PMD - which means that if | ||
1257 | * anybody is using __ka address to the initial boot-stack - and try | ||
1258 | * to use it - they are going to crash. The xen_start_info has been | ||
1259 | * taken care of already in xen_setup_kernel_pagetable. */ | ||
1260 | addr = xen_start_info->pt_base; | ||
1261 | size = roundup(xen_start_info->nr_pt_frames * PAGE_SIZE, PMD_SIZE); | ||
1262 | |||
1263 | xen_cleanhighmap(addr, addr + size); | ||
1264 | xen_start_info->pt_base = (unsigned long)__va(__pa(xen_start_info->pt_base)); | ||
1265 | #ifdef DEBUG | ||
1266 | /* This is superflous and is not neccessary, but you know what | ||
1267 | * lets do it. The MODULES_VADDR -> MODULES_END should be clear of | ||
1268 | * anything at this stage. */ | ||
1269 | xen_cleanhighmap(MODULES_VADDR, roundup(MODULES_VADDR, PUD_SIZE) - 1); | ||
1270 | #endif | ||
1271 | skip: | ||
1272 | #endif | ||
1273 | xen_post_allocator_init(); | ||
1274 | } | ||
1200 | static void xen_write_cr2(unsigned long cr2) | 1275 | static void xen_write_cr2(unsigned long cr2) |
1201 | { | 1276 | { |
1202 | this_cpu_read(xen_vcpu)->arch.cr2 = cr2; | 1277 | this_cpu_read(xen_vcpu)->arch.cr2 = cr2; |
@@ -1652,7 +1727,7 @@ static void set_page_prot(void *addr, pgprot_t prot) | |||
1652 | if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) | 1727 | if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0)) |
1653 | BUG(); | 1728 | BUG(); |
1654 | } | 1729 | } |
1655 | 1730 | #ifdef CONFIG_X86_32 | |
1656 | static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) | 1731 | static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) |
1657 | { | 1732 | { |
1658 | unsigned pmdidx, pteidx; | 1733 | unsigned pmdidx, pteidx; |
@@ -1703,7 +1778,7 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) | |||
1703 | 1778 | ||
1704 | set_page_prot(pmd, PAGE_KERNEL_RO); | 1779 | set_page_prot(pmd, PAGE_KERNEL_RO); |
1705 | } | 1780 | } |
1706 | 1781 | #endif | |
1707 | void __init xen_setup_machphys_mapping(void) | 1782 | void __init xen_setup_machphys_mapping(void) |
1708 | { | 1783 | { |
1709 | struct xen_machphys_mapping mapping; | 1784 | struct xen_machphys_mapping mapping; |
@@ -1731,7 +1806,20 @@ static void convert_pfn_mfn(void *v) | |||
1731 | for (i = 0; i < PTRS_PER_PTE; i++) | 1806 | for (i = 0; i < PTRS_PER_PTE; i++) |
1732 | pte[i] = xen_make_pte(pte[i].pte); | 1807 | pte[i] = xen_make_pte(pte[i].pte); |
1733 | } | 1808 | } |
1734 | 1809 | static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end, | |
1810 | unsigned long addr) | ||
1811 | { | ||
1812 | if (*pt_base == PFN_DOWN(__pa(addr))) { | ||
1813 | set_page_prot((void *)addr, PAGE_KERNEL); | ||
1814 | clear_page((void *)addr); | ||
1815 | (*pt_base)++; | ||
1816 | } | ||
1817 | if (*pt_end == PFN_DOWN(__pa(addr))) { | ||
1818 | set_page_prot((void *)addr, PAGE_KERNEL); | ||
1819 | clear_page((void *)addr); | ||
1820 | (*pt_end)--; | ||
1821 | } | ||
1822 | } | ||
1735 | /* | 1823 | /* |
1736 | * Set up the initial kernel pagetable. | 1824 | * Set up the initial kernel pagetable. |
1737 | * | 1825 | * |
@@ -1743,11 +1831,13 @@ static void convert_pfn_mfn(void *v) | |||
1743 | * of the physical mapping once some sort of allocator has been set | 1831 | * of the physical mapping once some sort of allocator has been set |
1744 | * up. | 1832 | * up. |
1745 | */ | 1833 | */ |
1746 | pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | 1834 | void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) |
1747 | unsigned long max_pfn) | ||
1748 | { | 1835 | { |
1749 | pud_t *l3; | 1836 | pud_t *l3; |
1750 | pmd_t *l2; | 1837 | pmd_t *l2; |
1838 | unsigned long addr[3]; | ||
1839 | unsigned long pt_base, pt_end; | ||
1840 | unsigned i; | ||
1751 | 1841 | ||
1752 | /* max_pfn_mapped is the last pfn mapped in the initial memory | 1842 | /* max_pfn_mapped is the last pfn mapped in the initial memory |
1753 | * mappings. Considering that on Xen after the kernel mappings we | 1843 | * mappings. Considering that on Xen after the kernel mappings we |
@@ -1755,32 +1845,53 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | |||
1755 | * set max_pfn_mapped to the last real pfn mapped. */ | 1845 | * set max_pfn_mapped to the last real pfn mapped. */ |
1756 | max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); | 1846 | max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); |
1757 | 1847 | ||
1848 | pt_base = PFN_DOWN(__pa(xen_start_info->pt_base)); | ||
1849 | pt_end = pt_base + xen_start_info->nr_pt_frames; | ||
1850 | |||
1758 | /* Zap identity mapping */ | 1851 | /* Zap identity mapping */ |
1759 | init_level4_pgt[0] = __pgd(0); | 1852 | init_level4_pgt[0] = __pgd(0); |
1760 | 1853 | ||
1761 | /* Pre-constructed entries are in pfn, so convert to mfn */ | 1854 | /* Pre-constructed entries are in pfn, so convert to mfn */ |
1855 | /* L4[272] -> level3_ident_pgt | ||
1856 | * L4[511] -> level3_kernel_pgt */ | ||
1762 | convert_pfn_mfn(init_level4_pgt); | 1857 | convert_pfn_mfn(init_level4_pgt); |
1858 | |||
1859 | /* L3_i[0] -> level2_ident_pgt */ | ||
1763 | convert_pfn_mfn(level3_ident_pgt); | 1860 | convert_pfn_mfn(level3_ident_pgt); |
1861 | /* L3_k[510] -> level2_kernel_pgt | ||
1862 | * L3_i[511] -> level2_fixmap_pgt */ | ||
1764 | convert_pfn_mfn(level3_kernel_pgt); | 1863 | convert_pfn_mfn(level3_kernel_pgt); |
1765 | 1864 | ||
1865 | /* We get [511][511] and have Xen's version of level2_kernel_pgt */ | ||
1766 | l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); | 1866 | l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); |
1767 | l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud); | 1867 | l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud); |
1768 | 1868 | ||
1769 | memcpy(level2_ident_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); | 1869 | addr[0] = (unsigned long)pgd; |
1770 | memcpy(level2_kernel_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); | 1870 | addr[1] = (unsigned long)l3; |
1771 | 1871 | addr[2] = (unsigned long)l2; | |
1872 | /* Graft it onto L4[272][0]. Note that we creating an aliasing problem: | ||
1873 | * Both L4[272][0] and L4[511][511] have entries that point to the same | ||
1874 | * L2 (PMD) tables. Meaning that if you modify it in __va space | ||
1875 | * it will be also modified in the __ka space! (But if you just | ||
1876 | * modify the PMD table to point to other PTE's or none, then you | ||
1877 | * are OK - which is what cleanup_highmap does) */ | ||
1878 | copy_page(level2_ident_pgt, l2); | ||
1879 | /* Graft it onto L4[511][511] */ | ||
1880 | copy_page(level2_kernel_pgt, l2); | ||
1881 | |||
1882 | /* Get [511][510] and graft that in level2_fixmap_pgt */ | ||
1772 | l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd); | 1883 | l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd); |
1773 | l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud); | 1884 | l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud); |
1774 | memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD); | 1885 | copy_page(level2_fixmap_pgt, l2); |
1775 | 1886 | /* Note that we don't do anything with level1_fixmap_pgt which | |
1776 | /* Set up identity map */ | 1887 | * we don't need. */ |
1777 | xen_map_identity_early(level2_ident_pgt, max_pfn); | ||
1778 | 1888 | ||
1779 | /* Make pagetable pieces RO */ | 1889 | /* Make pagetable pieces RO */ |
1780 | set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); | 1890 | set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); |
1781 | set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); | 1891 | set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); |
1782 | set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); | 1892 | set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); |
1783 | set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO); | 1893 | set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO); |
1894 | set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); | ||
1784 | set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); | 1895 | set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); |
1785 | set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); | 1896 | set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); |
1786 | 1897 | ||
@@ -1791,22 +1902,28 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | |||
1791 | /* Unpin Xen-provided one */ | 1902 | /* Unpin Xen-provided one */ |
1792 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); | 1903 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd))); |
1793 | 1904 | ||
1794 | /* Switch over */ | ||
1795 | pgd = init_level4_pgt; | ||
1796 | |||
1797 | /* | 1905 | /* |
1798 | * At this stage there can be no user pgd, and no page | 1906 | * At this stage there can be no user pgd, and no page |
1799 | * structure to attach it to, so make sure we just set kernel | 1907 | * structure to attach it to, so make sure we just set kernel |
1800 | * pgd. | 1908 | * pgd. |
1801 | */ | 1909 | */ |
1802 | xen_mc_batch(); | 1910 | xen_mc_batch(); |
1803 | __xen_write_cr3(true, __pa(pgd)); | 1911 | __xen_write_cr3(true, __pa(init_level4_pgt)); |
1804 | xen_mc_issue(PARAVIRT_LAZY_CPU); | 1912 | xen_mc_issue(PARAVIRT_LAZY_CPU); |
1805 | 1913 | ||
1806 | memblock_reserve(__pa(xen_start_info->pt_base), | 1914 | /* We can't that easily rip out L3 and L2, as the Xen pagetables are |
1807 | xen_start_info->nr_pt_frames * PAGE_SIZE); | 1915 | * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ... for |
1916 | * the initial domain. For guests using the toolstack, they are in: | ||
1917 | * [L4], [L3], [L2], [L1], [L1], order .. So for dom0 we can only | ||
1918 | * rip out the [L4] (pgd), but for guests we shave off three pages. | ||
1919 | */ | ||
1920 | for (i = 0; i < ARRAY_SIZE(addr); i++) | ||
1921 | check_pt_base(&pt_base, &pt_end, addr[i]); | ||
1808 | 1922 | ||
1809 | return pgd; | 1923 | /* Our (by three pages) smaller Xen pagetable that we are using */ |
1924 | memblock_reserve(PFN_PHYS(pt_base), (pt_end - pt_base) * PAGE_SIZE); | ||
1925 | /* Revector the xen_start_info */ | ||
1926 | xen_start_info = (struct start_info *)__va(__pa(xen_start_info)); | ||
1810 | } | 1927 | } |
1811 | #else /* !CONFIG_X86_64 */ | 1928 | #else /* !CONFIG_X86_64 */ |
1812 | static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); | 1929 | static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD); |
@@ -1831,8 +1948,7 @@ static void __init xen_write_cr3_init(unsigned long cr3) | |||
1831 | */ | 1948 | */ |
1832 | swapper_kernel_pmd = | 1949 | swapper_kernel_pmd = |
1833 | extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); | 1950 | extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE); |
1834 | memcpy(swapper_kernel_pmd, initial_kernel_pmd, | 1951 | copy_page(swapper_kernel_pmd, initial_kernel_pmd); |
1835 | sizeof(pmd_t) * PTRS_PER_PMD); | ||
1836 | swapper_pg_dir[KERNEL_PGD_BOUNDARY] = | 1952 | swapper_pg_dir[KERNEL_PGD_BOUNDARY] = |
1837 | __pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT); | 1953 | __pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT); |
1838 | set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO); | 1954 | set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO); |
@@ -1849,8 +1965,7 @@ static void __init xen_write_cr3_init(unsigned long cr3) | |||
1849 | pv_mmu_ops.write_cr3 = &xen_write_cr3; | 1965 | pv_mmu_ops.write_cr3 = &xen_write_cr3; |
1850 | } | 1966 | } |
1851 | 1967 | ||
1852 | pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | 1968 | void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn) |
1853 | unsigned long max_pfn) | ||
1854 | { | 1969 | { |
1855 | pmd_t *kernel_pmd; | 1970 | pmd_t *kernel_pmd; |
1856 | 1971 | ||
@@ -1862,11 +1977,11 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | |||
1862 | 512*1024); | 1977 | 512*1024); |
1863 | 1978 | ||
1864 | kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); | 1979 | kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); |
1865 | memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); | 1980 | copy_page(initial_kernel_pmd, kernel_pmd); |
1866 | 1981 | ||
1867 | xen_map_identity_early(initial_kernel_pmd, max_pfn); | 1982 | xen_map_identity_early(initial_kernel_pmd, max_pfn); |
1868 | 1983 | ||
1869 | memcpy(initial_page_table, pgd, sizeof(pgd_t) * PTRS_PER_PGD); | 1984 | copy_page(initial_page_table, pgd); |
1870 | initial_page_table[KERNEL_PGD_BOUNDARY] = | 1985 | initial_page_table[KERNEL_PGD_BOUNDARY] = |
1871 | __pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT); | 1986 | __pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT); |
1872 | 1987 | ||
@@ -1882,8 +1997,6 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, | |||
1882 | 1997 | ||
1883 | memblock_reserve(__pa(xen_start_info->pt_base), | 1998 | memblock_reserve(__pa(xen_start_info->pt_base), |
1884 | xen_start_info->nr_pt_frames * PAGE_SIZE); | 1999 | xen_start_info->nr_pt_frames * PAGE_SIZE); |
1885 | |||
1886 | return initial_page_table; | ||
1887 | } | 2000 | } |
1888 | #endif /* CONFIG_X86_64 */ | 2001 | #endif /* CONFIG_X86_64 */ |
1889 | 2002 | ||
@@ -2333,6 +2446,9 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | |||
2333 | unsigned long range; | 2446 | unsigned long range; |
2334 | int err = 0; | 2447 | int err = 0; |
2335 | 2448 | ||
2449 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
2450 | return -EINVAL; | ||
2451 | |||
2336 | prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP); | 2452 | prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP); |
2337 | 2453 | ||
2338 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_RESERVED | VM_IO)) == | 2454 | BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_RESERVED | VM_IO)) == |
@@ -2351,8 +2467,8 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, | |||
2351 | if (err) | 2467 | if (err) |
2352 | goto out; | 2468 | goto out; |
2353 | 2469 | ||
2354 | err = -EFAULT; | 2470 | err = HYPERVISOR_mmu_update(mmu_update, batch, NULL, domid); |
2355 | if (HYPERVISOR_mmu_update(mmu_update, batch, NULL, domid) < 0) | 2471 | if (err < 0) |
2356 | goto out; | 2472 | goto out; |
2357 | 2473 | ||
2358 | nr -= batch; | 2474 | nr -= batch; |
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 72213da605f5..95fb2aa5927e 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * | 22 | * |
23 | * P2M_PER_PAGE depends on the architecture, as a mfn is always | 23 | * P2M_PER_PAGE depends on the architecture, as a mfn is always |
24 | * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to | 24 | * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to |
25 | * 512 and 1024 entries respectively. | 25 | * 512 and 1024 entries respectively. |
26 | * | 26 | * |
27 | * In short, these structures contain the Machine Frame Number (MFN) of the PFN. | 27 | * In short, these structures contain the Machine Frame Number (MFN) of the PFN. |
28 | * | 28 | * |
@@ -139,11 +139,11 @@ | |||
139 | * / | ~0, ~0, .... | | 139 | * / | ~0, ~0, .... | |
140 | * | \---------------/ | 140 | * | \---------------/ |
141 | * | | 141 | * | |
142 | * p2m_missing p2m_missing | 142 | * p2m_mid_missing p2m_missing |
143 | * /------------------\ /------------\ | 143 | * /-----------------\ /------------\ |
144 | * | [p2m_mid_missing]+---->| ~0, ~0, ~0 | | 144 | * | [p2m_missing] +---->| ~0, ~0, ~0 | |
145 | * | [p2m_mid_missing]+---->| ..., ~0 | | 145 | * | [p2m_missing] +---->| ..., ~0 | |
146 | * \------------------/ \------------/ | 146 | * \-----------------/ \------------/ |
147 | * | 147 | * |
148 | * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT) | 148 | * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT) |
149 | */ | 149 | */ |
@@ -396,7 +396,85 @@ void __init xen_build_dynamic_phys_to_machine(void) | |||
396 | 396 | ||
397 | m2p_override_init(); | 397 | m2p_override_init(); |
398 | } | 398 | } |
399 | #ifdef CONFIG_X86_64 | ||
400 | #include <linux/bootmem.h> | ||
401 | unsigned long __init xen_revector_p2m_tree(void) | ||
402 | { | ||
403 | unsigned long va_start; | ||
404 | unsigned long va_end; | ||
405 | unsigned long pfn; | ||
406 | unsigned long pfn_free = 0; | ||
407 | unsigned long *mfn_list = NULL; | ||
408 | unsigned long size; | ||
409 | |||
410 | va_start = xen_start_info->mfn_list; | ||
411 | /*We copy in increments of P2M_PER_PAGE * sizeof(unsigned long), | ||
412 | * so make sure it is rounded up to that */ | ||
413 | size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long)); | ||
414 | va_end = va_start + size; | ||
415 | |||
416 | /* If we were revectored already, don't do it again. */ | ||
417 | if (va_start <= __START_KERNEL_map && va_start >= __PAGE_OFFSET) | ||
418 | return 0; | ||
419 | |||
420 | mfn_list = alloc_bootmem_align(size, PAGE_SIZE); | ||
421 | if (!mfn_list) { | ||
422 | pr_warn("Could not allocate space for a new P2M tree!\n"); | ||
423 | return xen_start_info->mfn_list; | ||
424 | } | ||
425 | /* Fill it out with INVALID_P2M_ENTRY value */ | ||
426 | memset(mfn_list, 0xFF, size); | ||
427 | |||
428 | for (pfn = 0; pfn < ALIGN(MAX_DOMAIN_PAGES, P2M_PER_PAGE); pfn += P2M_PER_PAGE) { | ||
429 | unsigned topidx = p2m_top_index(pfn); | ||
430 | unsigned mididx; | ||
431 | unsigned long *mid_p; | ||
432 | |||
433 | if (!p2m_top[topidx]) | ||
434 | continue; | ||
435 | |||
436 | if (p2m_top[topidx] == p2m_mid_missing) | ||
437 | continue; | ||
438 | |||
439 | mididx = p2m_mid_index(pfn); | ||
440 | mid_p = p2m_top[topidx][mididx]; | ||
441 | if (!mid_p) | ||
442 | continue; | ||
443 | if ((mid_p == p2m_missing) || (mid_p == p2m_identity)) | ||
444 | continue; | ||
445 | |||
446 | if ((unsigned long)mid_p == INVALID_P2M_ENTRY) | ||
447 | continue; | ||
448 | |||
449 | /* The old va. Rebase it on mfn_list */ | ||
450 | if (mid_p >= (unsigned long *)va_start && mid_p <= (unsigned long *)va_end) { | ||
451 | unsigned long *new; | ||
452 | |||
453 | if (pfn_free > (size / sizeof(unsigned long))) { | ||
454 | WARN(1, "Only allocated for %ld pages, but we want %ld!\n", | ||
455 | size / sizeof(unsigned long), pfn_free); | ||
456 | return 0; | ||
457 | } | ||
458 | new = &mfn_list[pfn_free]; | ||
459 | |||
460 | copy_page(new, mid_p); | ||
461 | p2m_top[topidx][mididx] = &mfn_list[pfn_free]; | ||
462 | p2m_top_mfn_p[topidx][mididx] = virt_to_mfn(&mfn_list[pfn_free]); | ||
463 | |||
464 | pfn_free += P2M_PER_PAGE; | ||
399 | 465 | ||
466 | } | ||
467 | /* This should be the leafs allocated for identity from _brk. */ | ||
468 | } | ||
469 | return (unsigned long)mfn_list; | ||
470 | |||
471 | } | ||
472 | #else | ||
473 | unsigned long __init xen_revector_p2m_tree(void) | ||
474 | { | ||
475 | return 0; | ||
476 | } | ||
477 | #endif | ||
400 | unsigned long get_phys_to_machine(unsigned long pfn) | 478 | unsigned long get_phys_to_machine(unsigned long pfn) |
401 | { | 479 | { |
402 | unsigned topidx, mididx, idx; | 480 | unsigned topidx, mididx, idx; |
@@ -430,7 +508,7 @@ static void free_p2m_page(void *p) | |||
430 | free_page((unsigned long)p); | 508 | free_page((unsigned long)p); |
431 | } | 509 | } |
432 | 510 | ||
433 | /* | 511 | /* |
434 | * Fully allocate the p2m structure for a given pfn. We need to check | 512 | * Fully allocate the p2m structure for a given pfn. We need to check |
435 | * that both the top and mid levels are allocated, and make sure the | 513 | * that both the top and mid levels are allocated, and make sure the |
436 | * parallel mfn tree is kept in sync. We may race with other cpus, so | 514 | * parallel mfn tree is kept in sync. We may race with other cpus, so |
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c index 967633ad98c4..969570491c39 100644 --- a/arch/x86/xen/pci-swiotlb-xen.c +++ b/arch/x86/xen/pci-swiotlb-xen.c | |||
@@ -8,6 +8,14 @@ | |||
8 | #include <xen/xen.h> | 8 | #include <xen/xen.h> |
9 | #include <asm/iommu_table.h> | 9 | #include <asm/iommu_table.h> |
10 | 10 | ||
11 | |||
12 | #include <asm/xen/swiotlb-xen.h> | ||
13 | #ifdef CONFIG_X86_64 | ||
14 | #include <asm/iommu.h> | ||
15 | #include <asm/dma.h> | ||
16 | #endif | ||
17 | #include <linux/export.h> | ||
18 | |||
11 | int xen_swiotlb __read_mostly; | 19 | int xen_swiotlb __read_mostly; |
12 | 20 | ||
13 | static struct dma_map_ops xen_swiotlb_dma_ops = { | 21 | static struct dma_map_ops xen_swiotlb_dma_ops = { |
@@ -34,34 +42,64 @@ static struct dma_map_ops xen_swiotlb_dma_ops = { | |||
34 | int __init pci_xen_swiotlb_detect(void) | 42 | int __init pci_xen_swiotlb_detect(void) |
35 | { | 43 | { |
36 | 44 | ||
45 | if (!xen_pv_domain()) | ||
46 | return 0; | ||
47 | |||
37 | /* If running as PV guest, either iommu=soft, or swiotlb=force will | 48 | /* If running as PV guest, either iommu=soft, or swiotlb=force will |
38 | * activate this IOMMU. If running as PV privileged, activate it | 49 | * activate this IOMMU. If running as PV privileged, activate it |
39 | * irregardless. | 50 | * irregardless. |
40 | */ | 51 | */ |
41 | if ((xen_initial_domain() || swiotlb || swiotlb_force) && | 52 | if ((xen_initial_domain() || swiotlb || swiotlb_force)) |
42 | (xen_pv_domain())) | ||
43 | xen_swiotlb = 1; | 53 | xen_swiotlb = 1; |
44 | 54 | ||
45 | /* If we are running under Xen, we MUST disable the native SWIOTLB. | 55 | /* If we are running under Xen, we MUST disable the native SWIOTLB. |
46 | * Don't worry about swiotlb_force flag activating the native, as | 56 | * Don't worry about swiotlb_force flag activating the native, as |
47 | * the 'swiotlb' flag is the only one turning it on. */ | 57 | * the 'swiotlb' flag is the only one turning it on. */ |
48 | if (xen_pv_domain()) | 58 | swiotlb = 0; |
49 | swiotlb = 0; | ||
50 | 59 | ||
60 | #ifdef CONFIG_X86_64 | ||
61 | /* pci_swiotlb_detect_4gb turns on native SWIOTLB if no_iommu == 0 | ||
62 | * (so no iommu=X command line over-writes). | ||
63 | * Considering that PV guests do not want the *native SWIOTLB* but | ||
64 | * only Xen SWIOTLB it is not useful to us so set no_iommu=1 here. | ||
65 | */ | ||
66 | if (max_pfn > MAX_DMA32_PFN) | ||
67 | no_iommu = 1; | ||
68 | #endif | ||
51 | return xen_swiotlb; | 69 | return xen_swiotlb; |
52 | } | 70 | } |
53 | 71 | ||
54 | void __init pci_xen_swiotlb_init(void) | 72 | void __init pci_xen_swiotlb_init(void) |
55 | { | 73 | { |
56 | if (xen_swiotlb) { | 74 | if (xen_swiotlb) { |
57 | xen_swiotlb_init(1); | 75 | xen_swiotlb_init(1, true /* early */); |
58 | dma_ops = &xen_swiotlb_dma_ops; | 76 | dma_ops = &xen_swiotlb_dma_ops; |
59 | 77 | ||
60 | /* Make sure ACS will be enabled */ | 78 | /* Make sure ACS will be enabled */ |
61 | pci_request_acs(); | 79 | pci_request_acs(); |
62 | } | 80 | } |
63 | } | 81 | } |
82 | |||
83 | int pci_xen_swiotlb_init_late(void) | ||
84 | { | ||
85 | int rc; | ||
86 | |||
87 | if (xen_swiotlb) | ||
88 | return 0; | ||
89 | |||
90 | rc = xen_swiotlb_init(1, false /* late */); | ||
91 | if (rc) | ||
92 | return rc; | ||
93 | |||
94 | dma_ops = &xen_swiotlb_dma_ops; | ||
95 | /* Make sure ACS will be enabled */ | ||
96 | pci_request_acs(); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(pci_xen_swiotlb_init_late); | ||
101 | |||
64 | IOMMU_INIT_FINISH(pci_xen_swiotlb_detect, | 102 | IOMMU_INIT_FINISH(pci_xen_swiotlb_detect, |
65 | 0, | 103 | NULL, |
66 | pci_xen_swiotlb_init, | 104 | pci_xen_swiotlb_init, |
67 | 0); | 105 | NULL); |
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c index ffcf2615640b..0a7852483ffe 100644 --- a/arch/x86/xen/platform-pci-unplug.c +++ b/arch/x86/xen/platform-pci-unplug.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | 25 | ||
26 | #include <xen/platform_pci.h> | 26 | #include <xen/platform_pci.h> |
27 | #include "xen-ops.h" | ||
27 | 28 | ||
28 | #define XEN_PLATFORM_ERR_MAGIC -1 | 29 | #define XEN_PLATFORM_ERR_MAGIC -1 |
29 | #define XEN_PLATFORM_ERR_PROTOCOL -2 | 30 | #define XEN_PLATFORM_ERR_PROTOCOL -2 |
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index e2d62d697b5d..8971a26d21ab 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c | |||
@@ -432,6 +432,24 @@ char * __init xen_memory_setup(void) | |||
432 | * - mfn_list | 432 | * - mfn_list |
433 | * - xen_start_info | 433 | * - xen_start_info |
434 | * See comment above "struct start_info" in <xen/interface/xen.h> | 434 | * See comment above "struct start_info" in <xen/interface/xen.h> |
435 | * We tried to make the the memblock_reserve more selective so | ||
436 | * that it would be clear what region is reserved. Sadly we ran | ||
437 | * in the problem wherein on a 64-bit hypervisor with a 32-bit | ||
438 | * initial domain, the pt_base has the cr3 value which is not | ||
439 | * neccessarily where the pagetable starts! As Jan put it: " | ||
440 | * Actually, the adjustment turns out to be correct: The page | ||
441 | * tables for a 32-on-64 dom0 get allocated in the order "first L1", | ||
442 | * "first L2", "first L3", so the offset to the page table base is | ||
443 | * indeed 2. When reading xen/include/public/xen.h's comment | ||
444 | * very strictly, this is not a violation (since there nothing is said | ||
445 | * that the first thing in the page table space is pointed to by | ||
446 | * pt_base; I admit that this seems to be implied though, namely | ||
447 | * do I think that it is implied that the page table space is the | ||
448 | * range [pt_base, pt_base + nt_pt_frames), whereas that | ||
449 | * range here indeed is [pt_base - 2, pt_base - 2 + nt_pt_frames), | ||
450 | * which - without a priori knowledge - the kernel would have | ||
451 | * difficulty to figure out)." - so lets just fall back to the | ||
452 | * easy way and reserve the whole region. | ||
435 | */ | 453 | */ |
436 | memblock_reserve(__pa(xen_start_info->mfn_list), | 454 | memblock_reserve(__pa(xen_start_info->mfn_list), |
437 | xen_start_info->pt_base - xen_start_info->mfn_list); | 455 | xen_start_info->pt_base - xen_start_info->mfn_list); |
diff --git a/arch/x86/xen/vga.c b/arch/x86/xen/vga.c index 1cd7f4d11e29..6722e3733f02 100644 --- a/arch/x86/xen/vga.c +++ b/arch/x86/xen/vga.c | |||
@@ -35,6 +35,7 @@ void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size) | |||
35 | info->u.text_mode_3.font_height; | 35 | info->u.text_mode_3.font_height; |
36 | break; | 36 | break; |
37 | 37 | ||
38 | case XEN_VGATYPE_EFI_LFB: | ||
38 | case XEN_VGATYPE_VESA_LFB: | 39 | case XEN_VGATYPE_VESA_LFB: |
39 | if (size < offsetof(struct dom0_vga_console_info, | 40 | if (size < offsetof(struct dom0_vga_console_info, |
40 | u.vesa_lfb.gbl_caps)) | 41 | u.vesa_lfb.gbl_caps)) |
@@ -54,6 +55,12 @@ void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size) | |||
54 | screen_info->blue_pos = info->u.vesa_lfb.blue_pos; | 55 | screen_info->blue_pos = info->u.vesa_lfb.blue_pos; |
55 | screen_info->rsvd_size = info->u.vesa_lfb.rsvd_size; | 56 | screen_info->rsvd_size = info->u.vesa_lfb.rsvd_size; |
56 | screen_info->rsvd_pos = info->u.vesa_lfb.rsvd_pos; | 57 | screen_info->rsvd_pos = info->u.vesa_lfb.rsvd_pos; |
58 | |||
59 | if (info->video_type == XEN_VGATYPE_EFI_LFB) { | ||
60 | screen_info->orig_video_isVGA = VIDEO_TYPE_EFI; | ||
61 | break; | ||
62 | } | ||
63 | |||
57 | if (size >= offsetof(struct dom0_vga_console_info, | 64 | if (size >= offsetof(struct dom0_vga_console_info, |
58 | u.vesa_lfb.gbl_caps) | 65 | u.vesa_lfb.gbl_caps) |
59 | + sizeof(info->u.vesa_lfb.gbl_caps)) | 66 | + sizeof(info->u.vesa_lfb.gbl_caps)) |
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S index aaa7291c9259..7faed5869e5b 100644 --- a/arch/x86/xen/xen-head.S +++ b/arch/x86/xen/xen-head.S | |||
@@ -28,9 +28,61 @@ ENTRY(startup_xen) | |||
28 | __FINIT | 28 | __FINIT |
29 | 29 | ||
30 | .pushsection .text | 30 | .pushsection .text |
31 | .align PAGE_SIZE | 31 | .balign PAGE_SIZE |
32 | ENTRY(hypercall_page) | 32 | ENTRY(hypercall_page) |
33 | .skip PAGE_SIZE | 33 | #define NEXT_HYPERCALL(x) \ |
34 | ENTRY(xen_hypercall_##x) \ | ||
35 | .skip 32 | ||
36 | |||
37 | NEXT_HYPERCALL(set_trap_table) | ||
38 | NEXT_HYPERCALL(mmu_update) | ||
39 | NEXT_HYPERCALL(set_gdt) | ||
40 | NEXT_HYPERCALL(stack_switch) | ||
41 | NEXT_HYPERCALL(set_callbacks) | ||
42 | NEXT_HYPERCALL(fpu_taskswitch) | ||
43 | NEXT_HYPERCALL(sched_op_compat) | ||
44 | NEXT_HYPERCALL(platform_op) | ||
45 | NEXT_HYPERCALL(set_debugreg) | ||
46 | NEXT_HYPERCALL(get_debugreg) | ||
47 | NEXT_HYPERCALL(update_descriptor) | ||
48 | NEXT_HYPERCALL(ni) | ||
49 | NEXT_HYPERCALL(memory_op) | ||
50 | NEXT_HYPERCALL(multicall) | ||
51 | NEXT_HYPERCALL(update_va_mapping) | ||
52 | NEXT_HYPERCALL(set_timer_op) | ||
53 | NEXT_HYPERCALL(event_channel_op_compat) | ||
54 | NEXT_HYPERCALL(xen_version) | ||
55 | NEXT_HYPERCALL(console_io) | ||
56 | NEXT_HYPERCALL(physdev_op_compat) | ||
57 | NEXT_HYPERCALL(grant_table_op) | ||
58 | NEXT_HYPERCALL(vm_assist) | ||
59 | NEXT_HYPERCALL(update_va_mapping_otherdomain) | ||
60 | NEXT_HYPERCALL(iret) | ||
61 | NEXT_HYPERCALL(vcpu_op) | ||
62 | NEXT_HYPERCALL(set_segment_base) | ||
63 | NEXT_HYPERCALL(mmuext_op) | ||
64 | NEXT_HYPERCALL(xsm_op) | ||
65 | NEXT_HYPERCALL(nmi_op) | ||
66 | NEXT_HYPERCALL(sched_op) | ||
67 | NEXT_HYPERCALL(callback_op) | ||
68 | NEXT_HYPERCALL(xenoprof_op) | ||
69 | NEXT_HYPERCALL(event_channel_op) | ||
70 | NEXT_HYPERCALL(physdev_op) | ||
71 | NEXT_HYPERCALL(hvm_op) | ||
72 | NEXT_HYPERCALL(sysctl) | ||
73 | NEXT_HYPERCALL(domctl) | ||
74 | NEXT_HYPERCALL(kexec_op) | ||
75 | NEXT_HYPERCALL(tmem_op) /* 38 */ | ||
76 | ENTRY(xen_hypercall_rsvr) | ||
77 | .skip 320 | ||
78 | NEXT_HYPERCALL(mca) /* 48 */ | ||
79 | NEXT_HYPERCALL(arch_1) | ||
80 | NEXT_HYPERCALL(arch_2) | ||
81 | NEXT_HYPERCALL(arch_3) | ||
82 | NEXT_HYPERCALL(arch_4) | ||
83 | NEXT_HYPERCALL(arch_5) | ||
84 | NEXT_HYPERCALL(arch_6) | ||
85 | .balign PAGE_SIZE | ||
34 | .popsection | 86 | .popsection |
35 | 87 | ||
36 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") | 88 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") |
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 202d4c150154..bb5a8105ea86 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h | |||
@@ -27,7 +27,7 @@ void xen_setup_mfn_list_list(void); | |||
27 | void xen_setup_shared_info(void); | 27 | void xen_setup_shared_info(void); |
28 | void xen_build_mfn_list_list(void); | 28 | void xen_build_mfn_list_list(void); |
29 | void xen_setup_machphys_mapping(void); | 29 | void xen_setup_machphys_mapping(void); |
30 | pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); | 30 | void xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn); |
31 | void xen_reserve_top(void); | 31 | void xen_reserve_top(void); |
32 | extern unsigned long xen_max_p2m_pfn; | 32 | extern unsigned long xen_max_p2m_pfn; |
33 | 33 | ||
@@ -45,6 +45,7 @@ void xen_hvm_init_shared_info(void); | |||
45 | void xen_unplug_emulated_devices(void); | 45 | void xen_unplug_emulated_devices(void); |
46 | 46 | ||
47 | void __init xen_build_dynamic_phys_to_machine(void); | 47 | void __init xen_build_dynamic_phys_to_machine(void); |
48 | unsigned long __init xen_revector_p2m_tree(void); | ||
48 | 49 | ||
49 | void xen_init_irq_ops(void); | 50 | void xen_init_irq_ops(void); |
50 | void xen_setup_timer(int cpu); | 51 | void xen_setup_timer(int cpu); |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 682633bfe00f..05593d882023 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -635,9 +635,7 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk) | |||
635 | return; | 635 | return; |
636 | 636 | ||
637 | BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op)); | 637 | BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op)); |
638 | ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op, | 638 | gnttab_batch_copy(netbk->grant_copy_op, npo.copy_prod); |
639 | npo.copy_prod); | ||
640 | BUG_ON(ret != 0); | ||
641 | 639 | ||
642 | while ((skb = __skb_dequeue(&rxq)) != NULL) { | 640 | while ((skb = __skb_dequeue(&rxq)) != NULL) { |
643 | sco = (struct skb_cb_overlay *)skb->cb; | 641 | sco = (struct skb_cb_overlay *)skb->cb; |
@@ -1460,18 +1458,15 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) | |||
1460 | static void xen_netbk_tx_action(struct xen_netbk *netbk) | 1458 | static void xen_netbk_tx_action(struct xen_netbk *netbk) |
1461 | { | 1459 | { |
1462 | unsigned nr_gops; | 1460 | unsigned nr_gops; |
1463 | int ret; | ||
1464 | 1461 | ||
1465 | nr_gops = xen_netbk_tx_build_gops(netbk); | 1462 | nr_gops = xen_netbk_tx_build_gops(netbk); |
1466 | 1463 | ||
1467 | if (nr_gops == 0) | 1464 | if (nr_gops == 0) |
1468 | return; | 1465 | return; |
1469 | ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, | ||
1470 | netbk->tx_copy_ops, nr_gops); | ||
1471 | BUG_ON(ret); | ||
1472 | 1466 | ||
1473 | xen_netbk_tx_submit(netbk); | 1467 | gnttab_batch_copy(netbk->tx_copy_ops, nr_gops); |
1474 | 1468 | ||
1469 | xen_netbk_tx_submit(netbk); | ||
1475 | } | 1470 | } |
1476 | 1471 | ||
1477 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) | 1472 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) |
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index def8d0b5620c..0aab85a51559 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
22 | #include <linux/time.h> | 22 | #include <linux/time.h> |
23 | 23 | ||
24 | #include <asm/xen/swiotlb-xen.h> | ||
24 | #define INVALID_GRANT_REF (0) | 25 | #define INVALID_GRANT_REF (0) |
25 | #define INVALID_EVTCHN (-1) | 26 | #define INVALID_EVTCHN (-1) |
26 | 27 | ||
@@ -236,7 +237,7 @@ static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn, | |||
236 | return errno_to_pcibios_err(do_pci_op(pdev, &op)); | 237 | return errno_to_pcibios_err(do_pci_op(pdev, &op)); |
237 | } | 238 | } |
238 | 239 | ||
239 | struct pci_ops pcifront_bus_ops = { | 240 | static struct pci_ops pcifront_bus_ops = { |
240 | .read = pcifront_bus_read, | 241 | .read = pcifront_bus_read, |
241 | .write = pcifront_bus_write, | 242 | .write = pcifront_bus_write, |
242 | }; | 243 | }; |
@@ -668,7 +669,7 @@ static irqreturn_t pcifront_handler_aer(int irq, void *dev) | |||
668 | schedule_pcifront_aer_op(pdev); | 669 | schedule_pcifront_aer_op(pdev); |
669 | return IRQ_HANDLED; | 670 | return IRQ_HANDLED; |
670 | } | 671 | } |
671 | static int pcifront_connect(struct pcifront_device *pdev) | 672 | static int pcifront_connect_and_init_dma(struct pcifront_device *pdev) |
672 | { | 673 | { |
673 | int err = 0; | 674 | int err = 0; |
674 | 675 | ||
@@ -681,9 +682,13 @@ static int pcifront_connect(struct pcifront_device *pdev) | |||
681 | dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n"); | 682 | dev_err(&pdev->xdev->dev, "PCI frontend already installed!\n"); |
682 | err = -EEXIST; | 683 | err = -EEXIST; |
683 | } | 684 | } |
684 | |||
685 | spin_unlock(&pcifront_dev_lock); | 685 | spin_unlock(&pcifront_dev_lock); |
686 | 686 | ||
687 | if (!err && !swiotlb_nr_tbl()) { | ||
688 | err = pci_xen_swiotlb_init_late(); | ||
689 | if (err) | ||
690 | dev_err(&pdev->xdev->dev, "Could not setup SWIOTLB!\n"); | ||
691 | } | ||
687 | return err; | 692 | return err; |
688 | } | 693 | } |
689 | 694 | ||
@@ -842,10 +847,10 @@ static int __devinit pcifront_try_connect(struct pcifront_device *pdev) | |||
842 | XenbusStateInitialised) | 847 | XenbusStateInitialised) |
843 | goto out; | 848 | goto out; |
844 | 849 | ||
845 | err = pcifront_connect(pdev); | 850 | err = pcifront_connect_and_init_dma(pdev); |
846 | if (err) { | 851 | if (err) { |
847 | xenbus_dev_fatal(pdev->xdev, err, | 852 | xenbus_dev_fatal(pdev->xdev, err, |
848 | "Error connecting PCI Frontend"); | 853 | "Error setting up PCI Frontend"); |
849 | goto out; | 854 | goto out; |
850 | } | 855 | } |
851 | 856 | ||
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 1e456dca4f60..2944ff88fdc0 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/console.h> | 21 | #include <linux/console.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/irq.h> | ||
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/types.h> | 26 | #include <linux/types.h> |
26 | #include <linux/list.h> | 27 | #include <linux/list.h> |
@@ -35,6 +36,7 @@ | |||
35 | #include <xen/page.h> | 36 | #include <xen/page.h> |
36 | #include <xen/events.h> | 37 | #include <xen/events.h> |
37 | #include <xen/interface/io/console.h> | 38 | #include <xen/interface/io/console.h> |
39 | #include <xen/interface/sched.h> | ||
38 | #include <xen/hvc-console.h> | 40 | #include <xen/hvc-console.h> |
39 | #include <xen/xenbus.h> | 41 | #include <xen/xenbus.h> |
40 | 42 | ||
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 7595581d032c..c60d1629c916 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -373,11 +373,22 @@ static void unmask_evtchn(int port) | |||
373 | { | 373 | { |
374 | struct shared_info *s = HYPERVISOR_shared_info; | 374 | struct shared_info *s = HYPERVISOR_shared_info; |
375 | unsigned int cpu = get_cpu(); | 375 | unsigned int cpu = get_cpu(); |
376 | int do_hypercall = 0, evtchn_pending = 0; | ||
376 | 377 | ||
377 | BUG_ON(!irqs_disabled()); | 378 | BUG_ON(!irqs_disabled()); |
378 | 379 | ||
379 | /* Slow path (hypercall) if this is a non-local port. */ | 380 | if (unlikely((cpu != cpu_from_evtchn(port)))) |
380 | if (unlikely(cpu != cpu_from_evtchn(port))) { | 381 | do_hypercall = 1; |
382 | else | ||
383 | evtchn_pending = sync_test_bit(port, &s->evtchn_pending[0]); | ||
384 | |||
385 | if (unlikely(evtchn_pending && xen_hvm_domain())) | ||
386 | do_hypercall = 1; | ||
387 | |||
388 | /* Slow path (hypercall) if this is a non-local port or if this is | ||
389 | * an hvm domain and an event is pending (hvm domains don't have | ||
390 | * their own implementation of irq_enable). */ | ||
391 | if (do_hypercall) { | ||
381 | struct evtchn_unmask unmask = { .port = port }; | 392 | struct evtchn_unmask unmask = { .port = port }; |
382 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); | 393 | (void)HYPERVISOR_event_channel_op(EVTCHNOP_unmask, &unmask); |
383 | } else { | 394 | } else { |
@@ -390,7 +401,7 @@ static void unmask_evtchn(int port) | |||
390 | * 'hw_resend_irq'. Just like a real IO-APIC we 'lose | 401 | * 'hw_resend_irq'. Just like a real IO-APIC we 'lose |
391 | * the interrupt edge' if the channel is masked. | 402 | * the interrupt edge' if the channel is masked. |
392 | */ | 403 | */ |
393 | if (sync_test_bit(port, &s->evtchn_pending[0]) && | 404 | if (evtchn_pending && |
394 | !sync_test_and_set_bit(port / BITS_PER_LONG, | 405 | !sync_test_and_set_bit(port / BITS_PER_LONG, |
395 | &vcpu_info->evtchn_pending_sel)) | 406 | &vcpu_info->evtchn_pending_sel)) |
396 | vcpu_info->evtchn_upcall_pending = 1; | 407 | vcpu_info->evtchn_upcall_pending = 1; |
@@ -831,6 +842,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) | |||
831 | struct irq_info *info = info_for_irq(irq); | 842 | struct irq_info *info = info_for_irq(irq); |
832 | WARN_ON(info == NULL || info->type != IRQT_EVTCHN); | 843 | WARN_ON(info == NULL || info->type != IRQT_EVTCHN); |
833 | } | 844 | } |
845 | irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN); | ||
834 | 846 | ||
835 | out: | 847 | out: |
836 | mutex_unlock(&irq_mapping_update_lock); | 848 | mutex_unlock(&irq_mapping_update_lock); |
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 7f1241608489..5df9fd847b2e 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -446,7 +446,7 @@ static void mn_release(struct mmu_notifier *mn, | |||
446 | spin_unlock(&priv->lock); | 446 | spin_unlock(&priv->lock); |
447 | } | 447 | } |
448 | 448 | ||
449 | struct mmu_notifier_ops gntdev_mmu_ops = { | 449 | static struct mmu_notifier_ops gntdev_mmu_ops = { |
450 | .release = mn_release, | 450 | .release = mn_release, |
451 | .invalidate_page = mn_invl_page, | 451 | .invalidate_page = mn_invl_page, |
452 | .invalidate_range_start = mn_invl_range_start, | 452 | .invalidate_range_start = mn_invl_range_start, |
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 006726688baf..b2b0a375b348 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
39 | #include <linux/uaccess.h> | 39 | #include <linux/uaccess.h> |
40 | #include <linux/io.h> | 40 | #include <linux/io.h> |
41 | #include <linux/delay.h> | ||
41 | #include <linux/hardirq.h> | 42 | #include <linux/hardirq.h> |
42 | 43 | ||
43 | #include <xen/xen.h> | 44 | #include <xen/xen.h> |
@@ -47,6 +48,7 @@ | |||
47 | #include <xen/interface/memory.h> | 48 | #include <xen/interface/memory.h> |
48 | #include <xen/hvc-console.h> | 49 | #include <xen/hvc-console.h> |
49 | #include <asm/xen/hypercall.h> | 50 | #include <asm/xen/hypercall.h> |
51 | #include <asm/xen/interface.h> | ||
50 | 52 | ||
51 | #include <asm/pgtable.h> | 53 | #include <asm/pgtable.h> |
52 | #include <asm/sync_bitops.h> | 54 | #include <asm/sync_bitops.h> |
@@ -285,10 +287,9 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame, | |||
285 | } | 287 | } |
286 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); | 288 | EXPORT_SYMBOL_GPL(gnttab_grant_foreign_access); |
287 | 289 | ||
288 | void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid, | 290 | static void gnttab_update_subpage_entry_v2(grant_ref_t ref, domid_t domid, |
289 | unsigned long frame, int flags, | 291 | unsigned long frame, int flags, |
290 | unsigned page_off, | 292 | unsigned page_off, unsigned length) |
291 | unsigned length) | ||
292 | { | 293 | { |
293 | gnttab_shared.v2[ref].sub_page.frame = frame; | 294 | gnttab_shared.v2[ref].sub_page.frame = frame; |
294 | gnttab_shared.v2[ref].sub_page.page_off = page_off; | 295 | gnttab_shared.v2[ref].sub_page.page_off = page_off; |
@@ -345,9 +346,9 @@ bool gnttab_subpage_grants_available(void) | |||
345 | } | 346 | } |
346 | EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available); | 347 | EXPORT_SYMBOL_GPL(gnttab_subpage_grants_available); |
347 | 348 | ||
348 | void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid, | 349 | static void gnttab_update_trans_entry_v2(grant_ref_t ref, domid_t domid, |
349 | int flags, domid_t trans_domid, | 350 | int flags, domid_t trans_domid, |
350 | grant_ref_t trans_gref) | 351 | grant_ref_t trans_gref) |
351 | { | 352 | { |
352 | gnttab_shared.v2[ref].transitive.trans_domid = trans_domid; | 353 | gnttab_shared.v2[ref].transitive.trans_domid = trans_domid; |
353 | gnttab_shared.v2[ref].transitive.gref = trans_gref; | 354 | gnttab_shared.v2[ref].transitive.gref = trans_gref; |
@@ -823,6 +824,52 @@ unsigned int gnttab_max_grant_frames(void) | |||
823 | } | 824 | } |
824 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); | 825 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); |
825 | 826 | ||
827 | /* Handling of paged out grant targets (GNTST_eagain) */ | ||
828 | #define MAX_DELAY 256 | ||
829 | static inline void | ||
830 | gnttab_retry_eagain_gop(unsigned int cmd, void *gop, int16_t *status, | ||
831 | const char *func) | ||
832 | { | ||
833 | unsigned delay = 1; | ||
834 | |||
835 | do { | ||
836 | BUG_ON(HYPERVISOR_grant_table_op(cmd, gop, 1)); | ||
837 | if (*status == GNTST_eagain) | ||
838 | msleep(delay++); | ||
839 | } while ((*status == GNTST_eagain) && (delay < MAX_DELAY)); | ||
840 | |||
841 | if (delay >= MAX_DELAY) { | ||
842 | printk(KERN_ERR "%s: %s eagain grant\n", func, current->comm); | ||
843 | *status = GNTST_bad_page; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count) | ||
848 | { | ||
849 | struct gnttab_map_grant_ref *op; | ||
850 | |||
851 | if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, batch, count)) | ||
852 | BUG(); | ||
853 | for (op = batch; op < batch + count; op++) | ||
854 | if (op->status == GNTST_eagain) | ||
855 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, op, | ||
856 | &op->status, __func__); | ||
857 | } | ||
858 | EXPORT_SYMBOL_GPL(gnttab_batch_map); | ||
859 | |||
860 | void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count) | ||
861 | { | ||
862 | struct gnttab_copy *op; | ||
863 | |||
864 | if (HYPERVISOR_grant_table_op(GNTTABOP_copy, batch, count)) | ||
865 | BUG(); | ||
866 | for (op = batch; op < batch + count; op++) | ||
867 | if (op->status == GNTST_eagain) | ||
868 | gnttab_retry_eagain_gop(GNTTABOP_copy, op, | ||
869 | &op->status, __func__); | ||
870 | } | ||
871 | EXPORT_SYMBOL_GPL(gnttab_batch_copy); | ||
872 | |||
826 | int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | 873 | int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, |
827 | struct gnttab_map_grant_ref *kmap_ops, | 874 | struct gnttab_map_grant_ref *kmap_ops, |
828 | struct page **pages, unsigned int count) | 875 | struct page **pages, unsigned int count) |
@@ -836,6 +883,12 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
836 | if (ret) | 883 | if (ret) |
837 | return ret; | 884 | return ret; |
838 | 885 | ||
886 | /* Retry eagain maps */ | ||
887 | for (i = 0; i < count; i++) | ||
888 | if (map_ops[i].status == GNTST_eagain) | ||
889 | gnttab_retry_eagain_gop(GNTTABOP_map_grant_ref, map_ops + i, | ||
890 | &map_ops[i].status, __func__); | ||
891 | |||
839 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 892 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
840 | return ret; | 893 | return ret; |
841 | 894 | ||
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index ccee0f16bcf8..ef6389580b8c 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
@@ -76,7 +76,7 @@ static void free_page_list(struct list_head *pages) | |||
76 | */ | 76 | */ |
77 | static int gather_array(struct list_head *pagelist, | 77 | static int gather_array(struct list_head *pagelist, |
78 | unsigned nelem, size_t size, | 78 | unsigned nelem, size_t size, |
79 | void __user *data) | 79 | const void __user *data) |
80 | { | 80 | { |
81 | unsigned pageidx; | 81 | unsigned pageidx; |
82 | void *pagedata; | 82 | void *pagedata; |
@@ -246,61 +246,117 @@ struct mmap_batch_state { | |||
246 | domid_t domain; | 246 | domid_t domain; |
247 | unsigned long va; | 247 | unsigned long va; |
248 | struct vm_area_struct *vma; | 248 | struct vm_area_struct *vma; |
249 | int err; | 249 | /* A tristate: |
250 | 250 | * 0 for no errors | |
251 | xen_pfn_t __user *user; | 251 | * 1 if at least one error has happened (and no |
252 | * -ENOENT errors have happened) | ||
253 | * -ENOENT if at least 1 -ENOENT has happened. | ||
254 | */ | ||
255 | int global_error; | ||
256 | /* An array for individual errors */ | ||
257 | int *err; | ||
258 | |||
259 | /* User-space mfn array to store errors in the second pass for V1. */ | ||
260 | xen_pfn_t __user *user_mfn; | ||
252 | }; | 261 | }; |
253 | 262 | ||
254 | static int mmap_batch_fn(void *data, void *state) | 263 | static int mmap_batch_fn(void *data, void *state) |
255 | { | 264 | { |
256 | xen_pfn_t *mfnp = data; | 265 | xen_pfn_t *mfnp = data; |
257 | struct mmap_batch_state *st = state; | 266 | struct mmap_batch_state *st = state; |
267 | int ret; | ||
268 | |||
269 | ret = xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1, | ||
270 | st->vma->vm_page_prot, st->domain); | ||
258 | 271 | ||
259 | if (xen_remap_domain_mfn_range(st->vma, st->va & PAGE_MASK, *mfnp, 1, | 272 | /* Store error code for second pass. */ |
260 | st->vma->vm_page_prot, st->domain) < 0) { | 273 | *(st->err++) = ret; |
261 | *mfnp |= 0xf0000000U; | 274 | |
262 | st->err++; | 275 | /* And see if it affects the global_error. */ |
276 | if (ret < 0) { | ||
277 | if (ret == -ENOENT) | ||
278 | st->global_error = -ENOENT; | ||
279 | else { | ||
280 | /* Record that at least one error has happened. */ | ||
281 | if (st->global_error == 0) | ||
282 | st->global_error = 1; | ||
283 | } | ||
263 | } | 284 | } |
264 | st->va += PAGE_SIZE; | 285 | st->va += PAGE_SIZE; |
265 | 286 | ||
266 | return 0; | 287 | return 0; |
267 | } | 288 | } |
268 | 289 | ||
269 | static int mmap_return_errors(void *data, void *state) | 290 | static int mmap_return_errors_v1(void *data, void *state) |
270 | { | 291 | { |
271 | xen_pfn_t *mfnp = data; | 292 | xen_pfn_t *mfnp = data; |
272 | struct mmap_batch_state *st = state; | 293 | struct mmap_batch_state *st = state; |
273 | 294 | int err = *(st->err++); | |
274 | return put_user(*mfnp, st->user++); | 295 | |
296 | /* | ||
297 | * V1 encodes the error codes in the 32bit top nibble of the | ||
298 | * mfn (with its known limitations vis-a-vis 64 bit callers). | ||
299 | */ | ||
300 | *mfnp |= (err == -ENOENT) ? | ||
301 | PRIVCMD_MMAPBATCH_PAGED_ERROR : | ||
302 | PRIVCMD_MMAPBATCH_MFN_ERROR; | ||
303 | return __put_user(*mfnp, st->user_mfn++); | ||
275 | } | 304 | } |
276 | 305 | ||
277 | static struct vm_operations_struct privcmd_vm_ops; | 306 | static struct vm_operations_struct privcmd_vm_ops; |
278 | 307 | ||
279 | static long privcmd_ioctl_mmap_batch(void __user *udata) | 308 | static long privcmd_ioctl_mmap_batch(void __user *udata, int version) |
280 | { | 309 | { |
281 | int ret; | 310 | int ret; |
282 | struct privcmd_mmapbatch m; | 311 | struct privcmd_mmapbatch_v2 m; |
283 | struct mm_struct *mm = current->mm; | 312 | struct mm_struct *mm = current->mm; |
284 | struct vm_area_struct *vma; | 313 | struct vm_area_struct *vma; |
285 | unsigned long nr_pages; | 314 | unsigned long nr_pages; |
286 | LIST_HEAD(pagelist); | 315 | LIST_HEAD(pagelist); |
316 | int *err_array = NULL; | ||
287 | struct mmap_batch_state state; | 317 | struct mmap_batch_state state; |
288 | 318 | ||
289 | if (!xen_initial_domain()) | 319 | if (!xen_initial_domain()) |
290 | return -EPERM; | 320 | return -EPERM; |
291 | 321 | ||
292 | if (copy_from_user(&m, udata, sizeof(m))) | 322 | switch (version) { |
293 | return -EFAULT; | 323 | case 1: |
324 | if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) | ||
325 | return -EFAULT; | ||
326 | /* Returns per-frame error in m.arr. */ | ||
327 | m.err = NULL; | ||
328 | if (!access_ok(VERIFY_WRITE, m.arr, m.num * sizeof(*m.arr))) | ||
329 | return -EFAULT; | ||
330 | break; | ||
331 | case 2: | ||
332 | if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch_v2))) | ||
333 | return -EFAULT; | ||
334 | /* Returns per-frame error code in m.err. */ | ||
335 | if (!access_ok(VERIFY_WRITE, m.err, m.num * (sizeof(*m.err)))) | ||
336 | return -EFAULT; | ||
337 | break; | ||
338 | default: | ||
339 | return -EINVAL; | ||
340 | } | ||
294 | 341 | ||
295 | nr_pages = m.num; | 342 | nr_pages = m.num; |
296 | if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT))) | 343 | if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT))) |
297 | return -EINVAL; | 344 | return -EINVAL; |
298 | 345 | ||
299 | ret = gather_array(&pagelist, m.num, sizeof(xen_pfn_t), | 346 | ret = gather_array(&pagelist, m.num, sizeof(xen_pfn_t), m.arr); |
300 | m.arr); | ||
301 | 347 | ||
302 | if (ret || list_empty(&pagelist)) | 348 | if (ret) |
303 | goto out; | 349 | goto out; |
350 | if (list_empty(&pagelist)) { | ||
351 | ret = -EINVAL; | ||
352 | goto out; | ||
353 | } | ||
354 | |||
355 | err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL); | ||
356 | if (err_array == NULL) { | ||
357 | ret = -ENOMEM; | ||
358 | goto out; | ||
359 | } | ||
304 | 360 | ||
305 | down_write(&mm->mmap_sem); | 361 | down_write(&mm->mmap_sem); |
306 | 362 | ||
@@ -315,24 +371,37 @@ static long privcmd_ioctl_mmap_batch(void __user *udata) | |||
315 | goto out; | 371 | goto out; |
316 | } | 372 | } |
317 | 373 | ||
318 | state.domain = m.dom; | 374 | state.domain = m.dom; |
319 | state.vma = vma; | 375 | state.vma = vma; |
320 | state.va = m.addr; | 376 | state.va = m.addr; |
321 | state.err = 0; | 377 | state.global_error = 0; |
378 | state.err = err_array; | ||
322 | 379 | ||
323 | ret = traverse_pages(m.num, sizeof(xen_pfn_t), | 380 | /* mmap_batch_fn guarantees ret == 0 */ |
324 | &pagelist, mmap_batch_fn, &state); | 381 | BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), |
382 | &pagelist, mmap_batch_fn, &state)); | ||
325 | 383 | ||
326 | up_write(&mm->mmap_sem); | 384 | up_write(&mm->mmap_sem); |
327 | 385 | ||
328 | if (state.err > 0) { | 386 | if (state.global_error && (version == 1)) { |
329 | state.user = m.arr; | 387 | /* Write back errors in second pass. */ |
388 | state.user_mfn = (xen_pfn_t *)m.arr; | ||
389 | state.err = err_array; | ||
330 | ret = traverse_pages(m.num, sizeof(xen_pfn_t), | 390 | ret = traverse_pages(m.num, sizeof(xen_pfn_t), |
331 | &pagelist, | 391 | &pagelist, mmap_return_errors_v1, &state); |
332 | mmap_return_errors, &state); | 392 | } else if (version == 2) { |
393 | ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); | ||
394 | if (ret) | ||
395 | ret = -EFAULT; | ||
333 | } | 396 | } |
334 | 397 | ||
398 | /* If we have not had any EFAULT-like global errors then set the global | ||
399 | * error to -ENOENT if necessary. */ | ||
400 | if ((ret == 0) && (state.global_error == -ENOENT)) | ||
401 | ret = -ENOENT; | ||
402 | |||
335 | out: | 403 | out: |
404 | kfree(err_array); | ||
336 | free_page_list(&pagelist); | 405 | free_page_list(&pagelist); |
337 | 406 | ||
338 | return ret; | 407 | return ret; |
@@ -354,7 +423,11 @@ static long privcmd_ioctl(struct file *file, | |||
354 | break; | 423 | break; |
355 | 424 | ||
356 | case IOCTL_PRIVCMD_MMAPBATCH: | 425 | case IOCTL_PRIVCMD_MMAPBATCH: |
357 | ret = privcmd_ioctl_mmap_batch(udata); | 426 | ret = privcmd_ioctl_mmap_batch(udata, 1); |
427 | break; | ||
428 | |||
429 | case IOCTL_PRIVCMD_MMAPBATCH_V2: | ||
430 | ret = privcmd_ioctl_mmap_batch(udata, 2); | ||
358 | break; | 431 | break; |
359 | 432 | ||
360 | default: | 433 | default: |
@@ -380,10 +453,6 @@ static struct vm_operations_struct privcmd_vm_ops = { | |||
380 | 453 | ||
381 | static int privcmd_mmap(struct file *file, struct vm_area_struct *vma) | 454 | static int privcmd_mmap(struct file *file, struct vm_area_struct *vma) |
382 | { | 455 | { |
383 | /* Unsupported for auto-translate guests. */ | ||
384 | if (xen_feature(XENFEAT_auto_translated_physmap)) | ||
385 | return -ENOSYS; | ||
386 | |||
387 | /* DONTCOPY is essential for Xen because copy_page_range doesn't know | 456 | /* DONTCOPY is essential for Xen because copy_page_range doesn't know |
388 | * how to recreate these mappings */ | 457 | * how to recreate these mappings */ |
389 | vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP; | 458 | vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP; |
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 4d519488d304..58db6df866ef 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c | |||
@@ -52,7 +52,7 @@ static unsigned long xen_io_tlb_nslabs; | |||
52 | * Quick lookup value of the bus address of the IOTLB. | 52 | * Quick lookup value of the bus address of the IOTLB. |
53 | */ | 53 | */ |
54 | 54 | ||
55 | u64 start_dma_addr; | 55 | static u64 start_dma_addr; |
56 | 56 | ||
57 | static dma_addr_t xen_phys_to_bus(phys_addr_t paddr) | 57 | static dma_addr_t xen_phys_to_bus(phys_addr_t paddr) |
58 | { | 58 | { |
@@ -144,31 +144,72 @@ xen_swiotlb_fixup(void *buf, size_t size, unsigned long nslabs) | |||
144 | } while (i < nslabs); | 144 | } while (i < nslabs); |
145 | return 0; | 145 | return 0; |
146 | } | 146 | } |
147 | static unsigned long xen_set_nslabs(unsigned long nr_tbl) | ||
148 | { | ||
149 | if (!nr_tbl) { | ||
150 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); | ||
151 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); | ||
152 | } else | ||
153 | xen_io_tlb_nslabs = nr_tbl; | ||
147 | 154 | ||
148 | void __init xen_swiotlb_init(int verbose) | 155 | return xen_io_tlb_nslabs << IO_TLB_SHIFT; |
156 | } | ||
157 | |||
158 | enum xen_swiotlb_err { | ||
159 | XEN_SWIOTLB_UNKNOWN = 0, | ||
160 | XEN_SWIOTLB_ENOMEM, | ||
161 | XEN_SWIOTLB_EFIXUP | ||
162 | }; | ||
163 | |||
164 | static const char *xen_swiotlb_error(enum xen_swiotlb_err err) | ||
165 | { | ||
166 | switch (err) { | ||
167 | case XEN_SWIOTLB_ENOMEM: | ||
168 | return "Cannot allocate Xen-SWIOTLB buffer\n"; | ||
169 | case XEN_SWIOTLB_EFIXUP: | ||
170 | return "Failed to get contiguous memory for DMA from Xen!\n"\ | ||
171 | "You either: don't have the permissions, do not have"\ | ||
172 | " enough free memory under 4GB, or the hypervisor memory"\ | ||
173 | " is too fragmented!"; | ||
174 | default: | ||
175 | break; | ||
176 | } | ||
177 | return ""; | ||
178 | } | ||
179 | int __ref xen_swiotlb_init(int verbose, bool early) | ||
149 | { | 180 | { |
150 | unsigned long bytes; | 181 | unsigned long bytes, order; |
151 | int rc = -ENOMEM; | 182 | int rc = -ENOMEM; |
152 | unsigned long nr_tbl; | 183 | enum xen_swiotlb_err m_ret = XEN_SWIOTLB_UNKNOWN; |
153 | char *m = NULL; | ||
154 | unsigned int repeat = 3; | 184 | unsigned int repeat = 3; |
155 | 185 | ||
156 | nr_tbl = swiotlb_nr_tbl(); | 186 | xen_io_tlb_nslabs = swiotlb_nr_tbl(); |
157 | if (nr_tbl) | ||
158 | xen_io_tlb_nslabs = nr_tbl; | ||
159 | else { | ||
160 | xen_io_tlb_nslabs = (64 * 1024 * 1024 >> IO_TLB_SHIFT); | ||
161 | xen_io_tlb_nslabs = ALIGN(xen_io_tlb_nslabs, IO_TLB_SEGSIZE); | ||
162 | } | ||
163 | retry: | 187 | retry: |
164 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; | 188 | bytes = xen_set_nslabs(xen_io_tlb_nslabs); |
165 | 189 | order = get_order(xen_io_tlb_nslabs << IO_TLB_SHIFT); | |
166 | /* | 190 | /* |
167 | * Get IO TLB memory from any location. | 191 | * Get IO TLB memory from any location. |
168 | */ | 192 | */ |
169 | xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); | 193 | if (early) |
194 | xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes)); | ||
195 | else { | ||
196 | #define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT)) | ||
197 | #define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT) | ||
198 | while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { | ||
199 | xen_io_tlb_start = (void *)__get_free_pages(__GFP_NOWARN, order); | ||
200 | if (xen_io_tlb_start) | ||
201 | break; | ||
202 | order--; | ||
203 | } | ||
204 | if (order != get_order(bytes)) { | ||
205 | pr_warn("Warning: only able to allocate %ld MB " | ||
206 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); | ||
207 | xen_io_tlb_nslabs = SLABS_PER_PAGE << order; | ||
208 | bytes = xen_io_tlb_nslabs << IO_TLB_SHIFT; | ||
209 | } | ||
210 | } | ||
170 | if (!xen_io_tlb_start) { | 211 | if (!xen_io_tlb_start) { |
171 | m = "Cannot allocate Xen-SWIOTLB buffer!\n"; | 212 | m_ret = XEN_SWIOTLB_ENOMEM; |
172 | goto error; | 213 | goto error; |
173 | } | 214 | } |
174 | xen_io_tlb_end = xen_io_tlb_start + bytes; | 215 | xen_io_tlb_end = xen_io_tlb_start + bytes; |
@@ -179,17 +220,22 @@ retry: | |||
179 | bytes, | 220 | bytes, |
180 | xen_io_tlb_nslabs); | 221 | xen_io_tlb_nslabs); |
181 | if (rc) { | 222 | if (rc) { |
182 | free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); | 223 | if (early) |
183 | m = "Failed to get contiguous memory for DMA from Xen!\n"\ | 224 | free_bootmem(__pa(xen_io_tlb_start), PAGE_ALIGN(bytes)); |
184 | "You either: don't have the permissions, do not have"\ | 225 | else { |
185 | " enough free memory under 4GB, or the hypervisor memory"\ | 226 | free_pages((unsigned long)xen_io_tlb_start, order); |
186 | "is too fragmented!"; | 227 | xen_io_tlb_start = NULL; |
228 | } | ||
229 | m_ret = XEN_SWIOTLB_EFIXUP; | ||
187 | goto error; | 230 | goto error; |
188 | } | 231 | } |
189 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); | 232 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); |
190 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | 233 | if (early) { |
191 | 234 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | |
192 | return; | 235 | rc = 0; |
236 | } else | ||
237 | rc = swiotlb_late_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs); | ||
238 | return rc; | ||
193 | error: | 239 | error: |
194 | if (repeat--) { | 240 | if (repeat--) { |
195 | xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */ | 241 | xen_io_tlb_nslabs = max(1024UL, /* Min is 2MB */ |
@@ -198,10 +244,13 @@ error: | |||
198 | (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20); | 244 | (xen_io_tlb_nslabs << IO_TLB_SHIFT) >> 20); |
199 | goto retry; | 245 | goto retry; |
200 | } | 246 | } |
201 | xen_raw_printk("%s (rc:%d)", m, rc); | 247 | pr_err("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); |
202 | panic("%s (rc:%d)", m, rc); | 248 | if (early) |
249 | panic("%s (rc:%d)", xen_swiotlb_error(m_ret), rc); | ||
250 | else | ||
251 | free_pages((unsigned long)xen_io_tlb_start, order); | ||
252 | return rc; | ||
203 | } | 253 | } |
204 | |||
205 | void * | 254 | void * |
206 | xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | 255 | xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, |
207 | dma_addr_t *dma_handle, gfp_t flags, | 256 | dma_addr_t *dma_handle, gfp_t flags, |
@@ -466,14 +515,6 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | |||
466 | } | 515 | } |
467 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs); | 516 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs); |
468 | 517 | ||
469 | int | ||
470 | xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | ||
471 | enum dma_data_direction dir) | ||
472 | { | ||
473 | return xen_swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL); | ||
474 | } | ||
475 | EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg); | ||
476 | |||
477 | /* | 518 | /* |
478 | * Unmap a set of streaming mode DMA translations. Again, cpu read rules | 519 | * Unmap a set of streaming mode DMA translations. Again, cpu read rules |
479 | * concerning calls here are the same as for swiotlb_unmap_page() above. | 520 | * concerning calls here are the same as for swiotlb_unmap_page() above. |
@@ -494,14 +535,6 @@ xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | |||
494 | } | 535 | } |
495 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs); | 536 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg_attrs); |
496 | 537 | ||
497 | void | ||
498 | xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems, | ||
499 | enum dma_data_direction dir) | ||
500 | { | ||
501 | return xen_swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL); | ||
502 | } | ||
503 | EXPORT_SYMBOL_GPL(xen_swiotlb_unmap_sg); | ||
504 | |||
505 | /* | 538 | /* |
506 | * Make physical memory consistent for a set of streaming mode DMA translations | 539 | * Make physical memory consistent for a set of streaming mode DMA translations |
507 | * after a transfer. | 540 | * after a transfer. |
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c index fdb6d229c9bb..5e5ad7e28858 100644 --- a/drivers/xen/sys-hypervisor.c +++ b/drivers/xen/sys-hypervisor.c | |||
@@ -114,7 +114,7 @@ static void xen_sysfs_version_destroy(void) | |||
114 | 114 | ||
115 | /* UUID */ | 115 | /* UUID */ |
116 | 116 | ||
117 | static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) | 117 | static ssize_t uuid_show_fallback(struct hyp_sysfs_attr *attr, char *buffer) |
118 | { | 118 | { |
119 | char *vm, *val; | 119 | char *vm, *val; |
120 | int ret; | 120 | int ret; |
@@ -135,6 +135,17 @@ static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) | |||
135 | return ret; | 135 | return ret; |
136 | } | 136 | } |
137 | 137 | ||
138 | static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
139 | { | ||
140 | xen_domain_handle_t uuid; | ||
141 | int ret; | ||
142 | ret = HYPERVISOR_xen_version(XENVER_guest_handle, uuid); | ||
143 | if (ret) | ||
144 | return uuid_show_fallback(attr, buffer); | ||
145 | ret = sprintf(buffer, "%pU\n", uuid); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
138 | HYPERVISOR_ATTR_RO(uuid); | 149 | HYPERVISOR_ATTR_RO(uuid); |
139 | 150 | ||
140 | static int __init xen_sysfs_uuid_init(void) | 151 | static int __init xen_sysfs_uuid_init(void) |
diff --git a/drivers/xen/tmem.c b/drivers/xen/tmem.c index 89f264c67420..144564e5eb29 100644 --- a/drivers/xen/tmem.c +++ b/drivers/xen/tmem.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/xen/hypercall.h> | 21 | #include <asm/xen/hypercall.h> |
22 | #include <asm/xen/page.h> | 22 | #include <asm/xen/page.h> |
23 | #include <asm/xen/hypervisor.h> | 23 | #include <asm/xen/hypervisor.h> |
24 | #include <xen/tmem.h> | ||
24 | 25 | ||
25 | #define TMEM_CONTROL 0 | 26 | #define TMEM_CONTROL 0 |
26 | #define TMEM_NEW_POOL 1 | 27 | #define TMEM_NEW_POOL 1 |
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 92ff01dbeb10..961d664e2d2f 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c | |||
@@ -362,6 +362,7 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) | |||
362 | else { | 362 | else { |
363 | dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); | 363 | dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); |
364 | __pci_reset_function_locked(dev); | 364 | __pci_reset_function_locked(dev); |
365 | pci_restore_state(dev); | ||
365 | } | 366 | } |
366 | /* Now disable the device (this also ensures some private device | 367 | /* Now disable the device (this also ensures some private device |
367 | * data is setup before we export) | 368 | * data is setup before we export) |
@@ -681,14 +682,14 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev) | |||
681 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" | 682 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" |
682 | " by HVM, kill it\n"); | 683 | " by HVM, kill it\n"); |
683 | kill_domain_by_device(psdev); | 684 | kill_domain_by_device(psdev); |
684 | goto release; | 685 | goto end; |
685 | } | 686 | } |
686 | 687 | ||
687 | if (!test_bit(_XEN_PCIB_AERHANDLER, | 688 | if (!test_bit(_XEN_PCIB_AERHANDLER, |
688 | (unsigned long *)&psdev->pdev->sh_info->flags)) { | 689 | (unsigned long *)&psdev->pdev->sh_info->flags)) { |
689 | dev_err(&dev->dev, | 690 | dev_err(&dev->dev, |
690 | "guest with no AER driver should have been killed\n"); | 691 | "guest with no AER driver should have been killed\n"); |
691 | goto release; | 692 | goto end; |
692 | } | 693 | } |
693 | result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result); | 694 | result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result); |
694 | 695 | ||
@@ -698,9 +699,9 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev) | |||
698 | "No AER slot_reset service or disconnected!\n"); | 699 | "No AER slot_reset service or disconnected!\n"); |
699 | kill_domain_by_device(psdev); | 700 | kill_domain_by_device(psdev); |
700 | } | 701 | } |
701 | release: | ||
702 | pcistub_device_put(psdev); | ||
703 | end: | 702 | end: |
703 | if (psdev) | ||
704 | pcistub_device_put(psdev); | ||
704 | up_write(&pcistub_sem); | 705 | up_write(&pcistub_sem); |
705 | return result; | 706 | return result; |
706 | 707 | ||
@@ -739,14 +740,14 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev) | |||
739 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" | 740 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" |
740 | " by HVM, kill it\n"); | 741 | " by HVM, kill it\n"); |
741 | kill_domain_by_device(psdev); | 742 | kill_domain_by_device(psdev); |
742 | goto release; | 743 | goto end; |
743 | } | 744 | } |
744 | 745 | ||
745 | if (!test_bit(_XEN_PCIB_AERHANDLER, | 746 | if (!test_bit(_XEN_PCIB_AERHANDLER, |
746 | (unsigned long *)&psdev->pdev->sh_info->flags)) { | 747 | (unsigned long *)&psdev->pdev->sh_info->flags)) { |
747 | dev_err(&dev->dev, | 748 | dev_err(&dev->dev, |
748 | "guest with no AER driver should have been killed\n"); | 749 | "guest with no AER driver should have been killed\n"); |
749 | goto release; | 750 | goto end; |
750 | } | 751 | } |
751 | result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result); | 752 | result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result); |
752 | 753 | ||
@@ -756,9 +757,9 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev) | |||
756 | "No AER mmio_enabled service or disconnected!\n"); | 757 | "No AER mmio_enabled service or disconnected!\n"); |
757 | kill_domain_by_device(psdev); | 758 | kill_domain_by_device(psdev); |
758 | } | 759 | } |
759 | release: | ||
760 | pcistub_device_put(psdev); | ||
761 | end: | 760 | end: |
761 | if (psdev) | ||
762 | pcistub_device_put(psdev); | ||
762 | up_write(&pcistub_sem); | 763 | up_write(&pcistub_sem); |
763 | return result; | 764 | return result; |
764 | } | 765 | } |
@@ -797,7 +798,7 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev, | |||
797 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" | 798 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" |
798 | " by HVM, kill it\n"); | 799 | " by HVM, kill it\n"); |
799 | kill_domain_by_device(psdev); | 800 | kill_domain_by_device(psdev); |
800 | goto release; | 801 | goto end; |
801 | } | 802 | } |
802 | 803 | ||
803 | /*Guest owns the device yet no aer handler regiested, kill guest*/ | 804 | /*Guest owns the device yet no aer handler regiested, kill guest*/ |
@@ -805,7 +806,7 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev, | |||
805 | (unsigned long *)&psdev->pdev->sh_info->flags)) { | 806 | (unsigned long *)&psdev->pdev->sh_info->flags)) { |
806 | dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n"); | 807 | dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n"); |
807 | kill_domain_by_device(psdev); | 808 | kill_domain_by_device(psdev); |
808 | goto release; | 809 | goto end; |
809 | } | 810 | } |
810 | result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result); | 811 | result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result); |
811 | 812 | ||
@@ -815,9 +816,9 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev, | |||
815 | "No AER error_detected service or disconnected!\n"); | 816 | "No AER error_detected service or disconnected!\n"); |
816 | kill_domain_by_device(psdev); | 817 | kill_domain_by_device(psdev); |
817 | } | 818 | } |
818 | release: | ||
819 | pcistub_device_put(psdev); | ||
820 | end: | 819 | end: |
820 | if (psdev) | ||
821 | pcistub_device_put(psdev); | ||
821 | up_write(&pcistub_sem); | 822 | up_write(&pcistub_sem); |
822 | return result; | 823 | return result; |
823 | } | 824 | } |
@@ -851,7 +852,7 @@ static void xen_pcibk_error_resume(struct pci_dev *dev) | |||
851 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" | 852 | dev_err(&dev->dev, DRV_NAME " device is not connected or owned" |
852 | " by HVM, kill it\n"); | 853 | " by HVM, kill it\n"); |
853 | kill_domain_by_device(psdev); | 854 | kill_domain_by_device(psdev); |
854 | goto release; | 855 | goto end; |
855 | } | 856 | } |
856 | 857 | ||
857 | if (!test_bit(_XEN_PCIB_AERHANDLER, | 858 | if (!test_bit(_XEN_PCIB_AERHANDLER, |
@@ -859,13 +860,13 @@ static void xen_pcibk_error_resume(struct pci_dev *dev) | |||
859 | dev_err(&dev->dev, | 860 | dev_err(&dev->dev, |
860 | "guest with no AER driver should have been killed\n"); | 861 | "guest with no AER driver should have been killed\n"); |
861 | kill_domain_by_device(psdev); | 862 | kill_domain_by_device(psdev); |
862 | goto release; | 863 | goto end; |
863 | } | 864 | } |
864 | common_process(psdev, 1, XEN_PCI_OP_aer_resume, | 865 | common_process(psdev, 1, XEN_PCI_OP_aer_resume, |
865 | PCI_ERS_RESULT_RECOVERED); | 866 | PCI_ERS_RESULT_RECOVERED); |
866 | release: | ||
867 | pcistub_device_put(psdev); | ||
868 | end: | 867 | end: |
868 | if (psdev) | ||
869 | pcistub_device_put(psdev); | ||
869 | up_write(&pcistub_sem); | 870 | up_write(&pcistub_sem); |
870 | return; | 871 | return; |
871 | } | 872 | } |
@@ -897,17 +898,41 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus, | |||
897 | int *slot, int *func) | 898 | int *slot, int *func) |
898 | { | 899 | { |
899 | int err; | 900 | int err; |
901 | char wc = '*'; | ||
900 | 902 | ||
901 | err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); | 903 | err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); |
902 | if (err == 4) | 904 | switch (err) { |
905 | case 3: | ||
906 | *func = -1; | ||
907 | err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc); | ||
908 | break; | ||
909 | case 2: | ||
910 | *slot = *func = -1; | ||
911 | err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc); | ||
912 | if (err >= 2) | ||
913 | ++err; | ||
914 | break; | ||
915 | } | ||
916 | if (err == 4 && wc == '*') | ||
903 | return 0; | 917 | return 0; |
904 | else if (err < 0) | 918 | else if (err < 0) |
905 | return -EINVAL; | 919 | return -EINVAL; |
906 | 920 | ||
907 | /* try again without domain */ | 921 | /* try again without domain */ |
908 | *domain = 0; | 922 | *domain = 0; |
923 | wc = '*'; | ||
909 | err = sscanf(buf, " %x:%x.%x", bus, slot, func); | 924 | err = sscanf(buf, " %x:%x.%x", bus, slot, func); |
910 | if (err == 3) | 925 | switch (err) { |
926 | case 2: | ||
927 | *func = -1; | ||
928 | err = sscanf(buf, " %x:%x.%c", bus, slot, &wc); | ||
929 | break; | ||
930 | case 1: | ||
931 | *slot = *func = -1; | ||
932 | err = sscanf(buf, " %x:*.%c", bus, &wc) + 1; | ||
933 | break; | ||
934 | } | ||
935 | if (err == 3 && wc == '*') | ||
911 | return 0; | 936 | return 0; |
912 | 937 | ||
913 | return -EINVAL; | 938 | return -EINVAL; |
@@ -930,6 +955,19 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func) | |||
930 | { | 955 | { |
931 | struct pcistub_device_id *pci_dev_id; | 956 | struct pcistub_device_id *pci_dev_id; |
932 | unsigned long flags; | 957 | unsigned long flags; |
958 | int rc = 0; | ||
959 | |||
960 | if (slot < 0) { | ||
961 | for (slot = 0; !rc && slot < 32; ++slot) | ||
962 | rc = pcistub_device_id_add(domain, bus, slot, func); | ||
963 | return rc; | ||
964 | } | ||
965 | |||
966 | if (func < 0) { | ||
967 | for (func = 0; !rc && func < 8; ++func) | ||
968 | rc = pcistub_device_id_add(domain, bus, slot, func); | ||
969 | return rc; | ||
970 | } | ||
933 | 971 | ||
934 | pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); | 972 | pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); |
935 | if (!pci_dev_id) | 973 | if (!pci_dev_id) |
@@ -952,15 +990,15 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func) | |||
952 | static int pcistub_device_id_remove(int domain, int bus, int slot, int func) | 990 | static int pcistub_device_id_remove(int domain, int bus, int slot, int func) |
953 | { | 991 | { |
954 | struct pcistub_device_id *pci_dev_id, *t; | 992 | struct pcistub_device_id *pci_dev_id, *t; |
955 | int devfn = PCI_DEVFN(slot, func); | ||
956 | int err = -ENOENT; | 993 | int err = -ENOENT; |
957 | unsigned long flags; | 994 | unsigned long flags; |
958 | 995 | ||
959 | spin_lock_irqsave(&device_ids_lock, flags); | 996 | spin_lock_irqsave(&device_ids_lock, flags); |
960 | list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, | 997 | list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, |
961 | slot_list) { | 998 | slot_list) { |
962 | if (pci_dev_id->domain == domain | 999 | if (pci_dev_id->domain == domain && pci_dev_id->bus == bus |
963 | && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) { | 1000 | && (slot < 0 || PCI_SLOT(pci_dev_id->devfn) == slot) |
1001 | && (func < 0 || PCI_FUNC(pci_dev_id->devfn) == func)) { | ||
964 | /* Don't break; here because it's possible the same | 1002 | /* Don't break; here because it's possible the same |
965 | * slot could be in the list more than once | 1003 | * slot could be in the list more than once |
966 | */ | 1004 | */ |
@@ -987,7 +1025,7 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, | |||
987 | struct config_field *field; | 1025 | struct config_field *field; |
988 | 1026 | ||
989 | psdev = pcistub_device_find(domain, bus, slot, func); | 1027 | psdev = pcistub_device_find(domain, bus, slot, func); |
990 | if (!psdev || !psdev->dev) { | 1028 | if (!psdev) { |
991 | err = -ENODEV; | 1029 | err = -ENODEV; |
992 | goto out; | 1030 | goto out; |
993 | } | 1031 | } |
@@ -1011,6 +1049,8 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, | |||
1011 | if (err) | 1049 | if (err) |
1012 | kfree(field); | 1050 | kfree(field); |
1013 | out: | 1051 | out: |
1052 | if (psdev) | ||
1053 | pcistub_device_put(psdev); | ||
1014 | return err; | 1054 | return err; |
1015 | } | 1055 | } |
1016 | 1056 | ||
@@ -1115,10 +1155,9 @@ static ssize_t pcistub_irq_handler_switch(struct device_driver *drv, | |||
1115 | 1155 | ||
1116 | err = str_to_slot(buf, &domain, &bus, &slot, &func); | 1156 | err = str_to_slot(buf, &domain, &bus, &slot, &func); |
1117 | if (err) | 1157 | if (err) |
1118 | goto out; | 1158 | return err; |
1119 | 1159 | ||
1120 | psdev = pcistub_device_find(domain, bus, slot, func); | 1160 | psdev = pcistub_device_find(domain, bus, slot, func); |
1121 | |||
1122 | if (!psdev) | 1161 | if (!psdev) |
1123 | goto out; | 1162 | goto out; |
1124 | 1163 | ||
@@ -1134,6 +1173,8 @@ static ssize_t pcistub_irq_handler_switch(struct device_driver *drv, | |||
1134 | if (dev_data->isr_on) | 1173 | if (dev_data->isr_on) |
1135 | dev_data->ack_intr = 1; | 1174 | dev_data->ack_intr = 1; |
1136 | out: | 1175 | out: |
1176 | if (psdev) | ||
1177 | pcistub_device_put(psdev); | ||
1137 | if (!err) | 1178 | if (!err) |
1138 | err = count; | 1179 | err = count; |
1139 | return err; | 1180 | return err; |
@@ -1216,15 +1257,16 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf, | |||
1216 | err = str_to_slot(buf, &domain, &bus, &slot, &func); | 1257 | err = str_to_slot(buf, &domain, &bus, &slot, &func); |
1217 | if (err) | 1258 | if (err) |
1218 | goto out; | 1259 | goto out; |
1260 | if (slot < 0 || func < 0) { | ||
1261 | err = -EINVAL; | ||
1262 | goto out; | ||
1263 | } | ||
1219 | psdev = pcistub_device_find(domain, bus, slot, func); | 1264 | psdev = pcistub_device_find(domain, bus, slot, func); |
1220 | if (!psdev) { | 1265 | if (!psdev) { |
1221 | err = -ENODEV; | 1266 | err = -ENODEV; |
1222 | goto out; | 1267 | goto out; |
1223 | } | 1268 | } |
1224 | if (!psdev->dev) { | 1269 | |
1225 | err = -ENODEV; | ||
1226 | goto release; | ||
1227 | } | ||
1228 | dev_data = pci_get_drvdata(psdev->dev); | 1270 | dev_data = pci_get_drvdata(psdev->dev); |
1229 | /* the driver data for a device should never be null at this point */ | 1271 | /* the driver data for a device should never be null at this point */ |
1230 | if (!dev_data) { | 1272 | if (!dev_data) { |
@@ -1297,17 +1339,51 @@ static int __init pcistub_init(void) | |||
1297 | 1339 | ||
1298 | if (pci_devs_to_hide && *pci_devs_to_hide) { | 1340 | if (pci_devs_to_hide && *pci_devs_to_hide) { |
1299 | do { | 1341 | do { |
1342 | char wc = '*'; | ||
1343 | |||
1300 | parsed = 0; | 1344 | parsed = 0; |
1301 | 1345 | ||
1302 | err = sscanf(pci_devs_to_hide + pos, | 1346 | err = sscanf(pci_devs_to_hide + pos, |
1303 | " (%x:%x:%x.%x) %n", | 1347 | " (%x:%x:%x.%x) %n", |
1304 | &domain, &bus, &slot, &func, &parsed); | 1348 | &domain, &bus, &slot, &func, &parsed); |
1305 | if (err != 4) { | 1349 | switch (err) { |
1350 | case 3: | ||
1351 | func = -1; | ||
1352 | err = sscanf(pci_devs_to_hide + pos, | ||
1353 | " (%x:%x:%x.%c) %n", | ||
1354 | &domain, &bus, &slot, &wc, | ||
1355 | &parsed); | ||
1356 | break; | ||
1357 | case 2: | ||
1358 | slot = func = -1; | ||
1359 | err = sscanf(pci_devs_to_hide + pos, | ||
1360 | " (%x:%x:*.%c) %n", | ||
1361 | &domain, &bus, &wc, &parsed) + 1; | ||
1362 | break; | ||
1363 | } | ||
1364 | |||
1365 | if (err != 4 || wc != '*') { | ||
1306 | domain = 0; | 1366 | domain = 0; |
1367 | wc = '*'; | ||
1307 | err = sscanf(pci_devs_to_hide + pos, | 1368 | err = sscanf(pci_devs_to_hide + pos, |
1308 | " (%x:%x.%x) %n", | 1369 | " (%x:%x.%x) %n", |
1309 | &bus, &slot, &func, &parsed); | 1370 | &bus, &slot, &func, &parsed); |
1310 | if (err != 3) | 1371 | switch (err) { |
1372 | case 2: | ||
1373 | func = -1; | ||
1374 | err = sscanf(pci_devs_to_hide + pos, | ||
1375 | " (%x:%x.%c) %n", | ||
1376 | &bus, &slot, &wc, | ||
1377 | &parsed); | ||
1378 | break; | ||
1379 | case 1: | ||
1380 | slot = func = -1; | ||
1381 | err = sscanf(pci_devs_to_hide + pos, | ||
1382 | " (%x:*.%c) %n", | ||
1383 | &bus, &wc, &parsed) + 1; | ||
1384 | break; | ||
1385 | } | ||
1386 | if (err != 3 || wc != '*') | ||
1311 | goto parse_error; | 1387 | goto parse_error; |
1312 | } | 1388 | } |
1313 | 1389 | ||
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index b3e146edb51d..bcf3ba4a6ec1 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c | |||
@@ -490,8 +490,7 @@ static int xenbus_map_ring_valloc_pv(struct xenbus_device *dev, | |||
490 | 490 | ||
491 | op.host_addr = arbitrary_virt_to_machine(pte).maddr; | 491 | op.host_addr = arbitrary_virt_to_machine(pte).maddr; |
492 | 492 | ||
493 | if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) | 493 | gnttab_batch_map(&op, 1); |
494 | BUG(); | ||
495 | 494 | ||
496 | if (op.status != GNTST_okay) { | 495 | if (op.status != GNTST_okay) { |
497 | free_vm_area(area); | 496 | free_vm_area(area); |
@@ -572,8 +571,7 @@ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref, | |||
572 | gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref, | 571 | gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map, gnt_ref, |
573 | dev->otherend_id); | 572 | dev->otherend_id); |
574 | 573 | ||
575 | if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) | 574 | gnttab_batch_map(&op, 1); |
576 | BUG(); | ||
577 | 575 | ||
578 | if (op.status != GNTST_okay) { | 576 | if (op.status != GNTST_okay) { |
579 | xenbus_dev_fatal(dev, op.status, | 577 | xenbus_dev_fatal(dev, op.status, |
diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index 52fe7ad07666..c5aa55c5d371 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c | |||
@@ -224,7 +224,7 @@ int xb_init_comms(void) | |||
224 | int err; | 224 | int err; |
225 | err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting, | 225 | err = bind_evtchn_to_irqhandler(xen_store_evtchn, wake_waiting, |
226 | 0, "xenbus", &xb_waitq); | 226 | 0, "xenbus", &xb_waitq); |
227 | if (err <= 0) { | 227 | if (err < 0) { |
228 | printk(KERN_ERR "XENBUS request irq failed %i\n", err); | 228 | printk(KERN_ERR "XENBUS request irq failed %i\n", err); |
229 | return err; | 229 | return err; |
230 | } | 230 | } |
diff --git a/drivers/xen/xenbus/xenbus_dev_backend.c b/drivers/xen/xenbus/xenbus_dev_backend.c index be738c43104b..d73000800762 100644 --- a/drivers/xen/xenbus/xenbus_dev_backend.c +++ b/drivers/xen/xenbus/xenbus_dev_backend.c | |||
@@ -107,7 +107,7 @@ static int xenbus_backend_mmap(struct file *file, struct vm_area_struct *vma) | |||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | const struct file_operations xenbus_backend_fops = { | 110 | static const struct file_operations xenbus_backend_fops = { |
111 | .open = xenbus_backend_open, | 111 | .open = xenbus_backend_open, |
112 | .mmap = xenbus_backend_mmap, | 112 | .mmap = xenbus_backend_mmap, |
113 | .unlocked_ioctl = xenbus_backend_ioctl, | 113 | .unlocked_ioctl = xenbus_backend_ioctl, |
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index b793723e724d..038b71dbf03c 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c | |||
@@ -324,8 +324,8 @@ static int cmp_dev(struct device *dev, void *data) | |||
324 | return 0; | 324 | return 0; |
325 | } | 325 | } |
326 | 326 | ||
327 | struct xenbus_device *xenbus_device_find(const char *nodename, | 327 | static struct xenbus_device *xenbus_device_find(const char *nodename, |
328 | struct bus_type *bus) | 328 | struct bus_type *bus) |
329 | { | 329 | { |
330 | struct xb_find_info info = { .dev = NULL, .nodename = nodename }; | 330 | struct xb_find_info info = { .dev = NULL, .nodename = nodename }; |
331 | 331 | ||
@@ -719,17 +719,47 @@ static int __init xenstored_local_init(void) | |||
719 | return err; | 719 | return err; |
720 | } | 720 | } |
721 | 721 | ||
722 | enum xenstore_init { | ||
723 | UNKNOWN, | ||
724 | PV, | ||
725 | HVM, | ||
726 | LOCAL, | ||
727 | }; | ||
722 | static int __init xenbus_init(void) | 728 | static int __init xenbus_init(void) |
723 | { | 729 | { |
724 | int err = 0; | 730 | int err = 0; |
731 | enum xenstore_init usage = UNKNOWN; | ||
732 | uint64_t v = 0; | ||
725 | 733 | ||
726 | if (!xen_domain()) | 734 | if (!xen_domain()) |
727 | return -ENODEV; | 735 | return -ENODEV; |
728 | 736 | ||
729 | xenbus_ring_ops_init(); | 737 | xenbus_ring_ops_init(); |
730 | 738 | ||
731 | if (xen_hvm_domain()) { | 739 | if (xen_pv_domain()) |
732 | uint64_t v = 0; | 740 | usage = PV; |
741 | if (xen_hvm_domain()) | ||
742 | usage = HVM; | ||
743 | if (xen_hvm_domain() && xen_initial_domain()) | ||
744 | usage = LOCAL; | ||
745 | if (xen_pv_domain() && !xen_start_info->store_evtchn) | ||
746 | usage = LOCAL; | ||
747 | if (xen_pv_domain() && xen_start_info->store_evtchn) | ||
748 | xenstored_ready = 1; | ||
749 | |||
750 | switch (usage) { | ||
751 | case LOCAL: | ||
752 | err = xenstored_local_init(); | ||
753 | if (err) | ||
754 | goto out_error; | ||
755 | xen_store_interface = mfn_to_virt(xen_store_mfn); | ||
756 | break; | ||
757 | case PV: | ||
758 | xen_store_evtchn = xen_start_info->store_evtchn; | ||
759 | xen_store_mfn = xen_start_info->store_mfn; | ||
760 | xen_store_interface = mfn_to_virt(xen_store_mfn); | ||
761 | break; | ||
762 | case HVM: | ||
733 | err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); | 763 | err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v); |
734 | if (err) | 764 | if (err) |
735 | goto out_error; | 765 | goto out_error; |
@@ -738,18 +768,12 @@ static int __init xenbus_init(void) | |||
738 | if (err) | 768 | if (err) |
739 | goto out_error; | 769 | goto out_error; |
740 | xen_store_mfn = (unsigned long)v; | 770 | xen_store_mfn = (unsigned long)v; |
741 | xen_store_interface = ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); | 771 | xen_store_interface = |
742 | } else { | 772 | ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE); |
743 | xen_store_evtchn = xen_start_info->store_evtchn; | 773 | break; |
744 | xen_store_mfn = xen_start_info->store_mfn; | 774 | default: |
745 | if (xen_store_evtchn) | 775 | pr_warn("Xenstore state unknown\n"); |
746 | xenstored_ready = 1; | 776 | break; |
747 | else { | ||
748 | err = xenstored_local_init(); | ||
749 | if (err) | ||
750 | goto out_error; | ||
751 | } | ||
752 | xen_store_interface = mfn_to_virt(xen_store_mfn); | ||
753 | } | 777 | } |
754 | 778 | ||
755 | /* Initialize the interface to xenstore. */ | 779 | /* Initialize the interface to xenstore. */ |
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index a31b54d48839..3159a37d966d 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <xen/xenbus.h> | 21 | #include <xen/xenbus.h> |
22 | #include <xen/events.h> | 22 | #include <xen/events.h> |
23 | #include <xen/page.h> | 23 | #include <xen/page.h> |
24 | #include <xen/xen.h> | ||
24 | 25 | ||
25 | #include <xen/platform_pci.h> | 26 | #include <xen/platform_pci.h> |
26 | 27 | ||
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index bce15cf4a8df..131dec04794e 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/rwsem.h> | 44 | #include <linux/rwsem.h> |
45 | #include <linux/module.h> | 45 | #include <linux/module.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <asm/xen/hypervisor.h> | ||
47 | #include <xen/xenbus.h> | 48 | #include <xen/xenbus.h> |
48 | #include <xen/xen.h> | 49 | #include <xen/xen.h> |
49 | #include "xenbus_comms.h" | 50 | #include "xenbus_comms.h" |
@@ -622,7 +623,7 @@ static void xs_reset_watches(void) | |||
622 | { | 623 | { |
623 | int err, supported = 0; | 624 | int err, supported = 0; |
624 | 625 | ||
625 | if (!xen_hvm_domain()) | 626 | if (!xen_hvm_domain() || xen_initial_domain()) |
626 | return; | 627 | return; |
627 | 628 | ||
628 | err = xenbus_scanf(XBT_NIL, "control", | 629 | err = xenbus_scanf(XBT_NIL, "control", |
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index e872526fdc5f..8d08b3ed406d 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h | |||
@@ -25,6 +25,7 @@ extern int swiotlb_force; | |||
25 | extern void swiotlb_init(int verbose); | 25 | extern void swiotlb_init(int verbose); |
26 | extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); | 26 | extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); |
27 | extern unsigned long swiotlb_nr_tbl(void); | 27 | extern unsigned long swiotlb_nr_tbl(void); |
28 | extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs); | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * Enumeration for sync targets | 31 | * Enumeration for sync targets |
diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index f19fff8650e9..aecee9d112cb 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h | |||
@@ -190,4 +190,16 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, | |||
190 | struct gnttab_map_grant_ref *kunmap_ops, | 190 | struct gnttab_map_grant_ref *kunmap_ops, |
191 | struct page **pages, unsigned int count); | 191 | struct page **pages, unsigned int count); |
192 | 192 | ||
193 | /* Perform a batch of grant map/copy operations. Retry every batch slot | ||
194 | * for which the hypervisor returns GNTST_eagain. This is typically due | ||
195 | * to paged out target frames. | ||
196 | * | ||
197 | * Will retry for 1, 2, ... 255 ms, i.e. 256 times during 32 seconds. | ||
198 | * | ||
199 | * Return value in each iand every status field of the batch guaranteed | ||
200 | * to not be GNTST_eagain. | ||
201 | */ | ||
202 | void gnttab_batch_map(struct gnttab_map_grant_ref *batch, unsigned count); | ||
203 | void gnttab_batch_copy(struct gnttab_copy *batch, unsigned count); | ||
204 | |||
193 | #endif /* __ASM_GNTTAB_H__ */ | 205 | #endif /* __ASM_GNTTAB_H__ */ |
diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h index a17d84433e6a..f9f8b975ae74 100644 --- a/include/xen/interface/grant_table.h +++ b/include/xen/interface/grant_table.h | |||
@@ -338,7 +338,7 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table); | |||
338 | #define GNTTABOP_transfer 4 | 338 | #define GNTTABOP_transfer 4 |
339 | struct gnttab_transfer { | 339 | struct gnttab_transfer { |
340 | /* IN parameters. */ | 340 | /* IN parameters. */ |
341 | unsigned long mfn; | 341 | xen_pfn_t mfn; |
342 | domid_t domid; | 342 | domid_t domid; |
343 | grant_ref_t ref; | 343 | grant_ref_t ref; |
344 | /* OUT parameters. */ | 344 | /* OUT parameters. */ |
@@ -375,7 +375,7 @@ struct gnttab_copy { | |||
375 | struct { | 375 | struct { |
376 | union { | 376 | union { |
377 | grant_ref_t ref; | 377 | grant_ref_t ref; |
378 | unsigned long gmfn; | 378 | xen_pfn_t gmfn; |
379 | } u; | 379 | } u; |
380 | domid_t domid; | 380 | domid_t domid; |
381 | uint16_t offset; | 381 | uint16_t offset; |
@@ -519,7 +519,9 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_get_version); | |||
519 | #define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */ | 519 | #define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */ |
520 | #define GNTST_permission_denied (-8) /* Not enough privilege for operation. */ | 520 | #define GNTST_permission_denied (-8) /* Not enough privilege for operation. */ |
521 | #define GNTST_bad_page (-9) /* Specified page was invalid for op. */ | 521 | #define GNTST_bad_page (-9) /* Specified page was invalid for op. */ |
522 | #define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary */ | 522 | #define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary. */ |
523 | #define GNTST_address_too_big (-11) /* transfer page address too large. */ | ||
524 | #define GNTST_eagain (-12) /* Operation not done; try again. */ | ||
523 | 525 | ||
524 | #define GNTTABOP_error_msgs { \ | 526 | #define GNTTABOP_error_msgs { \ |
525 | "okay", \ | 527 | "okay", \ |
@@ -532,7 +534,9 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_get_version); | |||
532 | "no spare translation slot in the I/O MMU", \ | 534 | "no spare translation slot in the I/O MMU", \ |
533 | "permission denied", \ | 535 | "permission denied", \ |
534 | "bad page", \ | 536 | "bad page", \ |
535 | "copy arguments cross page boundary" \ | 537 | "copy arguments cross page boundary", \ |
538 | "page address size too large", \ | ||
539 | "operation not done; try again" \ | ||
536 | } | 540 | } |
537 | 541 | ||
538 | #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */ | 542 | #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */ |
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index eac3ce153719..d8e33a93ea4d 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h | |||
@@ -31,7 +31,7 @@ struct xen_memory_reservation { | |||
31 | * OUT: GMFN bases of extents that were allocated | 31 | * OUT: GMFN bases of extents that were allocated |
32 | * (NB. This command also updates the mach_to_phys translation table) | 32 | * (NB. This command also updates the mach_to_phys translation table) |
33 | */ | 33 | */ |
34 | GUEST_HANDLE(ulong) extent_start; | 34 | GUEST_HANDLE(xen_pfn_t) extent_start; |
35 | 35 | ||
36 | /* Number of extents, and size/alignment of each (2^extent_order pages). */ | 36 | /* Number of extents, and size/alignment of each (2^extent_order pages). */ |
37 | unsigned long nr_extents; | 37 | unsigned long nr_extents; |
@@ -130,7 +130,7 @@ struct xen_machphys_mfn_list { | |||
130 | * any large discontiguities in the machine address space, 2MB gaps in | 130 | * any large discontiguities in the machine address space, 2MB gaps in |
131 | * the machphys table will be represented by an MFN base of zero. | 131 | * the machphys table will be represented by an MFN base of zero. |
132 | */ | 132 | */ |
133 | GUEST_HANDLE(ulong) extent_start; | 133 | GUEST_HANDLE(xen_pfn_t) extent_start; |
134 | 134 | ||
135 | /* | 135 | /* |
136 | * Number of extents written to the above array. This will be smaller | 136 | * Number of extents written to the above array. This will be smaller |
@@ -163,6 +163,9 @@ struct xen_add_to_physmap { | |||
163 | /* Which domain to change the mapping for. */ | 163 | /* Which domain to change the mapping for. */ |
164 | domid_t domid; | 164 | domid_t domid; |
165 | 165 | ||
166 | /* Number of pages to go through for gmfn_range */ | ||
167 | uint16_t size; | ||
168 | |||
166 | /* Source mapping space. */ | 169 | /* Source mapping space. */ |
167 | #define XENMAPSPACE_shared_info 0 /* shared info page */ | 170 | #define XENMAPSPACE_shared_info 0 /* shared info page */ |
168 | #define XENMAPSPACE_grant_table 1 /* grant table page */ | 171 | #define XENMAPSPACE_grant_table 1 /* grant table page */ |
@@ -172,7 +175,7 @@ struct xen_add_to_physmap { | |||
172 | unsigned long idx; | 175 | unsigned long idx; |
173 | 176 | ||
174 | /* GPFN where the source mapping page should appear. */ | 177 | /* GPFN where the source mapping page should appear. */ |
175 | unsigned long gpfn; | 178 | xen_pfn_t gpfn; |
176 | }; | 179 | }; |
177 | DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap); | 180 | DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap); |
178 | 181 | ||
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index 61fa66160983..54ad6f9e4725 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h | |||
@@ -54,7 +54,7 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_settime_t); | |||
54 | #define XENPF_add_memtype 31 | 54 | #define XENPF_add_memtype 31 |
55 | struct xenpf_add_memtype { | 55 | struct xenpf_add_memtype { |
56 | /* IN variables. */ | 56 | /* IN variables. */ |
57 | unsigned long mfn; | 57 | xen_pfn_t mfn; |
58 | uint64_t nr_mfns; | 58 | uint64_t nr_mfns; |
59 | uint32_t type; | 59 | uint32_t type; |
60 | /* OUT variables. */ | 60 | /* OUT variables. */ |
@@ -84,7 +84,7 @@ struct xenpf_read_memtype { | |||
84 | /* IN variables. */ | 84 | /* IN variables. */ |
85 | uint32_t reg; | 85 | uint32_t reg; |
86 | /* OUT variables. */ | 86 | /* OUT variables. */ |
87 | unsigned long mfn; | 87 | xen_pfn_t mfn; |
88 | uint64_t nr_mfns; | 88 | uint64_t nr_mfns; |
89 | uint32_t type; | 89 | uint32_t type; |
90 | }; | 90 | }; |
@@ -112,6 +112,7 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t); | |||
112 | #define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */ | 112 | #define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */ |
113 | #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */ | 113 | #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */ |
114 | #define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */ | 114 | #define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */ |
115 | #define XEN_FW_KBD_SHIFT_FLAGS 5 /* Int16, Fn02: Get keyboard shift flags. */ | ||
115 | struct xenpf_firmware_info { | 116 | struct xenpf_firmware_info { |
116 | /* IN variables. */ | 117 | /* IN variables. */ |
117 | uint32_t type; | 118 | uint32_t type; |
@@ -142,6 +143,8 @@ struct xenpf_firmware_info { | |||
142 | /* must refer to 128-byte buffer */ | 143 | /* must refer to 128-byte buffer */ |
143 | GUEST_HANDLE(uchar) edid; | 144 | GUEST_HANDLE(uchar) edid; |
144 | } vbeddc_info; /* XEN_FW_VBEDDC_INFO */ | 145 | } vbeddc_info; /* XEN_FW_VBEDDC_INFO */ |
146 | |||
147 | uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */ | ||
145 | } u; | 148 | } u; |
146 | }; | 149 | }; |
147 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_firmware_info_t); | 150 | DEFINE_GUEST_HANDLE_STRUCT(xenpf_firmware_info_t); |
diff --git a/include/xen/interface/version.h b/include/xen/interface/version.h index e8b6519d47e9..dd58cf5ea3e4 100644 --- a/include/xen/interface/version.h +++ b/include/xen/interface/version.h | |||
@@ -60,4 +60,7 @@ struct xen_feature_info { | |||
60 | /* arg == NULL; returns host memory page size. */ | 60 | /* arg == NULL; returns host memory page size. */ |
61 | #define XENVER_pagesize 7 | 61 | #define XENVER_pagesize 7 |
62 | 62 | ||
63 | /* arg == xen_domain_handle_t. */ | ||
64 | #define XENVER_guest_handle 8 | ||
65 | |||
63 | #endif /* __XEN_PUBLIC_VERSION_H__ */ | 66 | #endif /* __XEN_PUBLIC_VERSION_H__ */ |
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h index 0801468f9abe..886a5d80a18f 100644 --- a/include/xen/interface/xen.h +++ b/include/xen/interface/xen.h | |||
@@ -10,7 +10,6 @@ | |||
10 | #define __XEN_PUBLIC_XEN_H__ | 10 | #define __XEN_PUBLIC_XEN_H__ |
11 | 11 | ||
12 | #include <asm/xen/interface.h> | 12 | #include <asm/xen/interface.h> |
13 | #include <asm/pvclock-abi.h> | ||
14 | 13 | ||
15 | /* | 14 | /* |
16 | * XEN "SYSTEM CALLS" (a.k.a. HYPERCALLS). | 15 | * XEN "SYSTEM CALLS" (a.k.a. HYPERCALLS). |
@@ -190,7 +189,7 @@ struct mmuext_op { | |||
190 | unsigned int cmd; | 189 | unsigned int cmd; |
191 | union { | 190 | union { |
192 | /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */ | 191 | /* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR */ |
193 | unsigned long mfn; | 192 | xen_pfn_t mfn; |
194 | /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */ | 193 | /* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */ |
195 | unsigned long linear_addr; | 194 | unsigned long linear_addr; |
196 | } arg1; | 195 | } arg1; |
@@ -430,11 +429,11 @@ struct start_info { | |||
430 | unsigned long nr_pages; /* Total pages allocated to this domain. */ | 429 | unsigned long nr_pages; /* Total pages allocated to this domain. */ |
431 | unsigned long shared_info; /* MACHINE address of shared info struct. */ | 430 | unsigned long shared_info; /* MACHINE address of shared info struct. */ |
432 | uint32_t flags; /* SIF_xxx flags. */ | 431 | uint32_t flags; /* SIF_xxx flags. */ |
433 | unsigned long store_mfn; /* MACHINE page number of shared page. */ | 432 | xen_pfn_t store_mfn; /* MACHINE page number of shared page. */ |
434 | uint32_t store_evtchn; /* Event channel for store communication. */ | 433 | uint32_t store_evtchn; /* Event channel for store communication. */ |
435 | union { | 434 | union { |
436 | struct { | 435 | struct { |
437 | unsigned long mfn; /* MACHINE page number of console page. */ | 436 | xen_pfn_t mfn; /* MACHINE page number of console page. */ |
438 | uint32_t evtchn; /* Event channel for console page. */ | 437 | uint32_t evtchn; /* Event channel for console page. */ |
439 | } domU; | 438 | } domU; |
440 | struct { | 439 | struct { |
@@ -455,6 +454,7 @@ struct dom0_vga_console_info { | |||
455 | uint8_t video_type; | 454 | uint8_t video_type; |
456 | #define XEN_VGATYPE_TEXT_MODE_3 0x03 | 455 | #define XEN_VGATYPE_TEXT_MODE_3 0x03 |
457 | #define XEN_VGATYPE_VESA_LFB 0x23 | 456 | #define XEN_VGATYPE_VESA_LFB 0x23 |
457 | #define XEN_VGATYPE_EFI_LFB 0x70 | ||
458 | 458 | ||
459 | union { | 459 | union { |
460 | struct { | 460 | struct { |
diff --git a/include/xen/privcmd.h b/include/xen/privcmd.h index 17857fb4d550..a85316811d79 100644 --- a/include/xen/privcmd.h +++ b/include/xen/privcmd.h | |||
@@ -35,8 +35,7 @@ | |||
35 | 35 | ||
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/compiler.h> | 37 | #include <linux/compiler.h> |
38 | 38 | #include <xen/interface/xen.h> | |
39 | typedef unsigned long xen_pfn_t; | ||
40 | 39 | ||
41 | struct privcmd_hypercall { | 40 | struct privcmd_hypercall { |
42 | __u64 op; | 41 | __u64 op; |
@@ -59,13 +58,33 @@ struct privcmd_mmapbatch { | |||
59 | int num; /* number of pages to populate */ | 58 | int num; /* number of pages to populate */ |
60 | domid_t dom; /* target domain */ | 59 | domid_t dom; /* target domain */ |
61 | __u64 addr; /* virtual address */ | 60 | __u64 addr; /* virtual address */ |
62 | xen_pfn_t __user *arr; /* array of mfns - top nibble set on err */ | 61 | xen_pfn_t __user *arr; /* array of mfns - or'd with |
62 | PRIVCMD_MMAPBATCH_*_ERROR on err */ | ||
63 | }; | ||
64 | |||
65 | #define PRIVCMD_MMAPBATCH_MFN_ERROR 0xf0000000U | ||
66 | #define PRIVCMD_MMAPBATCH_PAGED_ERROR 0x80000000U | ||
67 | |||
68 | struct privcmd_mmapbatch_v2 { | ||
69 | unsigned int num; /* number of pages to populate */ | ||
70 | domid_t dom; /* target domain */ | ||
71 | __u64 addr; /* virtual address */ | ||
72 | const xen_pfn_t __user *arr; /* array of mfns */ | ||
73 | int __user *err; /* array of error codes */ | ||
63 | }; | 74 | }; |
64 | 75 | ||
65 | /* | 76 | /* |
66 | * @cmd: IOCTL_PRIVCMD_HYPERCALL | 77 | * @cmd: IOCTL_PRIVCMD_HYPERCALL |
67 | * @arg: &privcmd_hypercall_t | 78 | * @arg: &privcmd_hypercall_t |
68 | * Return: Value returned from execution of the specified hypercall. | 79 | * Return: Value returned from execution of the specified hypercall. |
80 | * | ||
81 | * @cmd: IOCTL_PRIVCMD_MMAPBATCH_V2 | ||
82 | * @arg: &struct privcmd_mmapbatch_v2 | ||
83 | * Return: 0 on success (i.e., arg->err contains valid error codes for | ||
84 | * each frame). On an error other than a failed frame remap, -1 is | ||
85 | * returned and errno is set to EINVAL, EFAULT etc. As an exception, | ||
86 | * if the operation was otherwise successful but any frame failed with | ||
87 | * -ENOENT, then -1 is returned and errno is set to ENOENT. | ||
69 | */ | 88 | */ |
70 | #define IOCTL_PRIVCMD_HYPERCALL \ | 89 | #define IOCTL_PRIVCMD_HYPERCALL \ |
71 | _IOC(_IOC_NONE, 'P', 0, sizeof(struct privcmd_hypercall)) | 90 | _IOC(_IOC_NONE, 'P', 0, sizeof(struct privcmd_hypercall)) |
@@ -73,5 +92,7 @@ struct privcmd_mmapbatch { | |||
73 | _IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap)) | 92 | _IOC(_IOC_NONE, 'P', 2, sizeof(struct privcmd_mmap)) |
74 | #define IOCTL_PRIVCMD_MMAPBATCH \ | 93 | #define IOCTL_PRIVCMD_MMAPBATCH \ |
75 | _IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch)) | 94 | _IOC(_IOC_NONE, 'P', 3, sizeof(struct privcmd_mmapbatch)) |
95 | #define IOCTL_PRIVCMD_MMAPBATCH_V2 \ | ||
96 | _IOC(_IOC_NONE, 'P', 4, sizeof(struct privcmd_mmapbatch_v2)) | ||
76 | 97 | ||
77 | #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ | 98 | #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */ |
diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h index 4f4d449f00f6..de8bcc641c49 100644 --- a/include/xen/swiotlb-xen.h +++ b/include/xen/swiotlb-xen.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/swiotlb.h> | 4 | #include <linux/swiotlb.h> |
5 | 5 | ||
6 | extern void xen_swiotlb_init(int verbose); | 6 | extern int xen_swiotlb_init(int verbose, bool early); |
7 | 7 | ||
8 | extern void | 8 | extern void |
9 | *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, | 9 | *xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, |
@@ -23,15 +23,6 @@ extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, | |||
23 | extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, | 23 | extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, |
24 | size_t size, enum dma_data_direction dir, | 24 | size_t size, enum dma_data_direction dir, |
25 | struct dma_attrs *attrs); | 25 | struct dma_attrs *attrs); |
26 | /* | ||
27 | extern int | ||
28 | xen_swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, | ||
29 | enum dma_data_direction dir); | ||
30 | |||
31 | extern void | ||
32 | xen_swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, | ||
33 | enum dma_data_direction dir); | ||
34 | */ | ||
35 | extern int | 26 | extern int |
36 | xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, | 27 | xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, |
37 | int nelems, enum dma_data_direction dir, | 28 | int nelems, enum dma_data_direction dir, |
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 45bc1f83a5ad..f114bf6a8e13 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c | |||
@@ -170,7 +170,7 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | |||
170 | * Statically reserve bounce buffer space and initialize bounce buffer data | 170 | * Statically reserve bounce buffer space and initialize bounce buffer data |
171 | * structures for the software IO TLB used to implement the DMA API. | 171 | * structures for the software IO TLB used to implement the DMA API. |
172 | */ | 172 | */ |
173 | void __init | 173 | static void __init |
174 | swiotlb_init_with_default_size(size_t default_size, int verbose) | 174 | swiotlb_init_with_default_size(size_t default_size, int verbose) |
175 | { | 175 | { |
176 | unsigned long bytes; | 176 | unsigned long bytes; |
@@ -206,8 +206,9 @@ swiotlb_init(int verbose) | |||
206 | int | 206 | int |
207 | swiotlb_late_init_with_default_size(size_t default_size) | 207 | swiotlb_late_init_with_default_size(size_t default_size) |
208 | { | 208 | { |
209 | unsigned long i, bytes, req_nslabs = io_tlb_nslabs; | 209 | unsigned long bytes, req_nslabs = io_tlb_nslabs; |
210 | unsigned int order; | 210 | unsigned int order; |
211 | int rc = 0; | ||
211 | 212 | ||
212 | if (!io_tlb_nslabs) { | 213 | if (!io_tlb_nslabs) { |
213 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); | 214 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); |
@@ -229,16 +230,32 @@ swiotlb_late_init_with_default_size(size_t default_size) | |||
229 | order--; | 230 | order--; |
230 | } | 231 | } |
231 | 232 | ||
232 | if (!io_tlb_start) | 233 | if (!io_tlb_start) { |
233 | goto cleanup1; | 234 | io_tlb_nslabs = req_nslabs; |
234 | 235 | return -ENOMEM; | |
236 | } | ||
235 | if (order != get_order(bytes)) { | 237 | if (order != get_order(bytes)) { |
236 | printk(KERN_WARNING "Warning: only able to allocate %ld MB " | 238 | printk(KERN_WARNING "Warning: only able to allocate %ld MB " |
237 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); | 239 | "for software IO TLB\n", (PAGE_SIZE << order) >> 20); |
238 | io_tlb_nslabs = SLABS_PER_PAGE << order; | 240 | io_tlb_nslabs = SLABS_PER_PAGE << order; |
239 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; | ||
240 | } | 241 | } |
242 | rc = swiotlb_late_init_with_tbl(io_tlb_start, io_tlb_nslabs); | ||
243 | if (rc) | ||
244 | free_pages((unsigned long)io_tlb_start, order); | ||
245 | return rc; | ||
246 | } | ||
247 | |||
248 | int | ||
249 | swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs) | ||
250 | { | ||
251 | unsigned long i, bytes; | ||
252 | |||
253 | bytes = nslabs << IO_TLB_SHIFT; | ||
254 | |||
255 | io_tlb_nslabs = nslabs; | ||
256 | io_tlb_start = tlb; | ||
241 | io_tlb_end = io_tlb_start + bytes; | 257 | io_tlb_end = io_tlb_start + bytes; |
258 | |||
242 | memset(io_tlb_start, 0, bytes); | 259 | memset(io_tlb_start, 0, bytes); |
243 | 260 | ||
244 | /* | 261 | /* |
@@ -288,10 +305,8 @@ cleanup3: | |||
288 | io_tlb_list = NULL; | 305 | io_tlb_list = NULL; |
289 | cleanup2: | 306 | cleanup2: |
290 | io_tlb_end = NULL; | 307 | io_tlb_end = NULL; |
291 | free_pages((unsigned long)io_tlb_start, order); | ||
292 | io_tlb_start = NULL; | 308 | io_tlb_start = NULL; |
293 | cleanup1: | 309 | io_tlb_nslabs = 0; |
294 | io_tlb_nslabs = req_nslabs; | ||
295 | return -ENOMEM; | 310 | return -ENOMEM; |
296 | } | 311 | } |
297 | 312 | ||