Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'stable/for-linus-3.18-b-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen bug fixes from David Vrabel:

- Fix regression in xen_clocksource_read() which caused all Xen guests
to crash early in boot.
- Several fixes for super rare race conditions in the p2m.
- Assorted other minor fixes.

* tag 'stable/for-linus-3.18-b-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
xen/pci: Allocate memory for physdev_pci_device_add's optarr
x86/xen: panic on bad Xen-provided memory map
x86/xen: Fix incorrect per_cpu accessor in xen_clocksource_read()
x86/xen: avoid race in p2m handling
x86/xen: delay construction of mfn_list_list
x86/xen: avoid writing to freed memory after race in p2m handling
xen/balloon: Don't continue ballooning when BP_ECANCELED is encountered

+50 -74
-3
arch/x86/xen/enlighten.c
··· 1636 1636 xen_raw_console_write("mapping kernel into physical memory\n"); 1637 1637 xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base, xen_start_info->nr_pages); 1638 1638 1639 - /* Allocate and initialize top and mid mfn levels for p2m structure */ 1640 - xen_build_mfn_list_list(); 1641 - 1642 1639 /* keep using Xen gdt for now; no urgent need to change it */ 1643 1640 1644 1641 #ifdef CONFIG_X86_32
+4 -1
arch/x86/xen/mmu.c
··· 1217 1217 static void __init xen_pagetable_init(void) 1218 1218 { 1219 1219 paging_init(); 1220 - xen_setup_shared_info(); 1221 1220 #ifdef CONFIG_X86_64 1222 1221 xen_pagetable_p2m_copy(); 1223 1222 #endif 1223 + /* Allocate and initialize top and mid mfn levels for p2m structure */ 1224 + xen_build_mfn_list_list(); 1225 + 1226 + xen_setup_shared_info(); 1224 1227 xen_post_allocator_init(); 1225 1228 } 1226 1229 static void xen_write_cr2(unsigned long cr2)
+25 -58
arch/x86/xen/p2m.c
··· 163 163 #include <linux/hash.h> 164 164 #include <linux/sched.h> 165 165 #include <linux/seq_file.h> 166 + #include <linux/bootmem.h> 166 167 167 168 #include <asm/cache.h> 168 169 #include <asm/setup.h> ··· 182 181 183 182 unsigned long xen_max_p2m_pfn __read_mostly; 184 183 184 + static unsigned long *p2m_mid_missing_mfn; 185 + static unsigned long *p2m_top_mfn; 186 + static unsigned long **p2m_top_mfn_p; 187 + 185 188 /* Placeholders for holes in the address space */ 186 189 static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE); 187 190 static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE); 188 - static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_missing_mfn, P2M_MID_PER_PAGE); 189 191 190 192 static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE); 191 - static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE); 192 - static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE); 193 193 194 194 static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE); 195 195 static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_identity, P2M_MID_PER_PAGE); 196 - static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE); 197 196 198 197 RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); 199 - RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); 200 198 201 199 /* For each I/O range remapped we may lose up to two leaf pages for the boundary 202 200 * violations and three mid pages to cover up to 3GB. With ··· 272 272 * Build the parallel p2m_top_mfn and p2m_mid_mfn structures 273 273 * 274 274 * This is called both at boot time, and after resuming from suspend: 275 - * - At boot time we're called very early, and must use extend_brk() 275 + * - At boot time we're called rather early, and must use alloc_bootmem*() 276 276 * to allocate memory. 277 277 * 278 278 * - After resume we're called from within stop_machine, but the mfn 279 - * tree should alreay be completely allocated. 279 + * tree should already be completely allocated. 280 280 */ 281 281 void __ref xen_build_mfn_list_list(void) 282 282 { ··· 287 287 288 288 /* Pre-initialize p2m_top_mfn to be completely missing */ 289 289 if (p2m_top_mfn == NULL) { 290 - p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE); 290 + p2m_mid_missing_mfn = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE); 291 291 p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing); 292 - p2m_mid_identity_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE); 293 - p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity); 294 292 295 - p2m_top_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE); 293 + p2m_top_mfn_p = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE); 296 294 p2m_top_mfn_p_init(p2m_top_mfn_p); 297 295 298 - p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE); 296 + p2m_top_mfn = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE); 299 297 p2m_top_mfn_init(p2m_top_mfn); 300 298 } else { 301 299 /* Reinitialise, mfn's all change after migration */ 302 300 p2m_mid_mfn_init(p2m_mid_missing_mfn, p2m_missing); 303 - p2m_mid_mfn_init(p2m_mid_identity_mfn, p2m_identity); 304 301 } 305 302 306 303 for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) { ··· 325 328 /* 326 329 * XXX boot-time only! We should never find 327 330 * missing parts of the mfn tree after 328 - * runtime. extend_brk() will BUG if we call 329 - * it too late. 331 + * runtime. 330 332 */ 331 - mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE); 333 + mid_mfn_p = alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE); 332 334 p2m_mid_mfn_init(mid_mfn_p, p2m_missing); 333 335 334 336 p2m_top_mfn_p[topidx] = mid_mfn_p; ··· 411 415 m2p_override_init(); 412 416 } 413 417 #ifdef CONFIG_X86_64 414 - #include <linux/bootmem.h> 415 418 unsigned long __init xen_revector_p2m_tree(void) 416 419 { 417 420 unsigned long va_start; ··· 472 477 473 478 copy_page(new, mid_p); 474 479 p2m_top[topidx][mididx] = &mfn_list[pfn_free]; 475 - p2m_top_mfn_p[topidx][mididx] = virt_to_mfn(&mfn_list[pfn_free]); 476 480 477 481 pfn_free += P2M_PER_PAGE; 478 482 ··· 532 538 unsigned topidx, mididx; 533 539 unsigned long ***top_p, **mid; 534 540 unsigned long *top_mfn_p, *mid_mfn; 541 + unsigned long *p2m_orig; 535 542 536 543 topidx = p2m_top_index(pfn); 537 544 mididx = p2m_mid_index(pfn); 538 545 539 546 top_p = &p2m_top[topidx]; 540 - mid = *top_p; 547 + mid = ACCESS_ONCE(*top_p); 541 548 542 549 if (mid == p2m_mid_missing) { 543 550 /* Mid level is missing, allocate a new one */ ··· 553 558 } 554 559 555 560 top_mfn_p = &p2m_top_mfn[topidx]; 556 - mid_mfn = p2m_top_mfn_p[topidx]; 561 + mid_mfn = ACCESS_ONCE(p2m_top_mfn_p[topidx]); 557 562 558 563 BUG_ON(virt_to_mfn(mid_mfn) != *top_mfn_p); 559 564 ··· 561 566 /* Separately check the mid mfn level */ 562 567 unsigned long missing_mfn; 563 568 unsigned long mid_mfn_mfn; 569 + unsigned long old_mfn; 564 570 565 571 mid_mfn = alloc_p2m_page(); 566 572 if (!mid_mfn) ··· 571 575 572 576 missing_mfn = virt_to_mfn(p2m_mid_missing_mfn); 573 577 mid_mfn_mfn = virt_to_mfn(mid_mfn); 574 - if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn) 578 + old_mfn = cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn); 579 + if (old_mfn != missing_mfn) { 575 580 free_p2m_page(mid_mfn); 576 - else 581 + mid_mfn = mfn_to_virt(old_mfn); 582 + } else { 577 583 p2m_top_mfn_p[topidx] = mid_mfn; 584 + } 578 585 } 579 586 580 - if (p2m_top[topidx][mididx] == p2m_identity || 581 - p2m_top[topidx][mididx] == p2m_missing) { 587 + p2m_orig = ACCESS_ONCE(p2m_top[topidx][mididx]); 588 + if (p2m_orig == p2m_identity || p2m_orig == p2m_missing) { 582 589 /* p2m leaf page is missing */ 583 590 unsigned long *p2m; 584 - unsigned long *p2m_orig = p2m_top[topidx][mididx]; 585 591 586 592 p2m = alloc_p2m_page(); 587 593 if (!p2m) ··· 604 606 { 605 607 unsigned topidx, mididx, idx; 606 608 unsigned long *p2m; 607 - unsigned long *mid_mfn_p; 608 609 609 610 topidx = p2m_top_index(pfn); 610 611 mididx = p2m_mid_index(pfn); ··· 630 633 631 634 p2m_top[topidx][mididx] = p2m; 632 635 633 - /* For save/restore we need to MFN of the P2M saved */ 634 - 635 - mid_mfn_p = p2m_top_mfn_p[topidx]; 636 - WARN(mid_mfn_p[mididx] != virt_to_mfn(p2m_missing), 637 - "P2M_TOP_P[%d][%d] != MFN of p2m_missing!\n", 638 - topidx, mididx); 639 - mid_mfn_p[mididx] = virt_to_mfn(p2m); 640 - 641 636 return true; 642 637 } 643 638 644 639 static bool __init early_alloc_p2m_middle(unsigned long pfn) 645 640 { 646 641 unsigned topidx = p2m_top_index(pfn); 647 - unsigned long *mid_mfn_p; 648 642 unsigned long **mid; 649 643 650 644 mid = p2m_top[topidx]; 651 - mid_mfn_p = p2m_top_mfn_p[topidx]; 652 645 if (mid == p2m_mid_missing) { 653 646 mid = extend_brk(PAGE_SIZE, PAGE_SIZE); 654 647 655 648 p2m_mid_init(mid, p2m_missing); 656 649 657 650 p2m_top[topidx] = mid; 658 - 659 - BUG_ON(mid_mfn_p != p2m_mid_missing_mfn); 660 - } 661 - /* And the save/restore P2M tables.. */ 662 - if (mid_mfn_p == p2m_mid_missing_mfn) { 663 - mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE); 664 - p2m_mid_mfn_init(mid_mfn_p, p2m_missing); 665 - 666 - p2m_top_mfn_p[topidx] = mid_mfn_p; 667 - p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p); 668 - /* Note: we don't set mid_mfn_p[midix] here, 669 - * look in early_alloc_p2m() */ 670 651 } 671 652 return true; 672 653 } ··· 655 680 * replace the P2M leaf with a p2m_missing or p2m_identity. 656 681 * Stick the old page in the new P2M tree location. 657 682 */ 658 - bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_mfn) 683 + static bool __init early_can_reuse_p2m_middle(unsigned long set_pfn) 659 684 { 660 685 unsigned topidx; 661 686 unsigned mididx; 662 687 unsigned ident_pfns; 663 688 unsigned inv_pfns; 664 689 unsigned long *p2m; 665 - unsigned long *mid_mfn_p; 666 690 unsigned idx; 667 691 unsigned long pfn; 668 692 ··· 707 733 found: 708 734 /* Found one, replace old with p2m_identity or p2m_missing */ 709 735 p2m_top[topidx][mididx] = (ident_pfns ? p2m_identity : p2m_missing); 710 - /* And the other for save/restore.. */ 711 - mid_mfn_p = p2m_top_mfn_p[topidx]; 712 - /* NOTE: Even if it is a p2m_identity it should still be point to 713 - * a page filled with INVALID_P2M_ENTRY entries. */ 714 - mid_mfn_p[mididx] = virt_to_mfn(p2m_missing); 715 736 716 737 /* Reset where we want to stick the old page in. */ 717 738 topidx = p2m_top_index(set_pfn); ··· 721 752 722 753 p2m_init(p2m); 723 754 p2m_top[topidx][mididx] = p2m; 724 - mid_mfn_p = p2m_top_mfn_p[topidx]; 725 - mid_mfn_p[mididx] = virt_to_mfn(p2m); 726 755 727 756 return true; 728 757 } ··· 730 763 if (!early_alloc_p2m_middle(pfn)) 731 764 return false; 732 765 733 - if (early_can_reuse_p2m_middle(pfn, mfn)) 766 + if (early_can_reuse_p2m_middle(pfn)) 734 767 return __set_phys_to_machine(pfn, mfn); 735 768 736 769 if (!early_alloc_p2m(pfn, false /* boundary crossover OK!*/))
+1
arch/x86/xen/setup.c
··· 595 595 rc = 0; 596 596 } 597 597 BUG_ON(rc); 598 + BUG_ON(memmap.nr_entries == 0); 598 599 599 600 /* 600 601 * Xen won't allow a 1:1 mapping to be created to UNUSABLE
+1 -1
arch/x86/xen/time.c
··· 158 158 cycle_t ret; 159 159 160 160 preempt_disable_notrace(); 161 - src = this_cpu_ptr(&xen_vcpu->time); 161 + src = &__this_cpu_read(xen_vcpu)->time; 162 162 ret = pvclock_clocksource_read(src); 163 163 preempt_enable_notrace(); 164 164 return ret;
+3
drivers/xen/balloon.c
··· 167 167 168 168 static enum bp_state update_schedule(enum bp_state state) 169 169 { 170 + if (state == BP_ECANCELED) 171 + return BP_ECANCELED; 172 + 170 173 if (state == BP_DONE) { 171 174 balloon_stats.schedule_delay = 1; 172 175 balloon_stats.retry_count = 1;
+16 -11
drivers/xen/pci.c
··· 41 41 #endif 42 42 43 43 if (pci_seg_supported) { 44 - struct physdev_pci_device_add add = { 45 - .seg = pci_domain_nr(pci_dev->bus), 46 - .bus = pci_dev->bus->number, 47 - .devfn = pci_dev->devfn 44 + struct { 45 + struct physdev_pci_device_add add; 46 + uint32_t pxm; 47 + } add_ext = { 48 + .add.seg = pci_domain_nr(pci_dev->bus), 49 + .add.bus = pci_dev->bus->number, 50 + .add.devfn = pci_dev->devfn 48 51 }; 52 + struct physdev_pci_device_add *add = &add_ext.add; 53 + 49 54 #ifdef CONFIG_ACPI 50 55 acpi_handle handle; 51 56 #endif 52 57 53 58 #ifdef CONFIG_PCI_IOV 54 59 if (pci_dev->is_virtfn) { 55 - add.flags = XEN_PCI_DEV_VIRTFN; 56 - add.physfn.bus = physfn->bus->number; 57 - add.physfn.devfn = physfn->devfn; 60 + add->flags = XEN_PCI_DEV_VIRTFN; 61 + add->physfn.bus = physfn->bus->number; 62 + add->physfn.devfn = physfn->devfn; 58 63 } else 59 64 #endif 60 65 if (pci_ari_enabled(pci_dev->bus) && PCI_SLOT(pci_dev->devfn)) 61 - add.flags = XEN_PCI_DEV_EXTFN; 66 + add->flags = XEN_PCI_DEV_EXTFN; 62 67 63 68 #ifdef CONFIG_ACPI 64 69 handle = ACPI_HANDLE(&pci_dev->dev); ··· 82 77 status = acpi_evaluate_integer(handle, "_PXM", 83 78 NULL, &pxm); 84 79 if (ACPI_SUCCESS(status)) { 85 - add.optarr[0] = pxm; 86 - add.flags |= XEN_PCI_DEV_PXM; 80 + add->optarr[0] = pxm; 81 + add->flags |= XEN_PCI_DEV_PXM; 87 82 break; 88 83 } 89 84 status = acpi_get_parent(handle, &handle); ··· 91 86 } 92 87 #endif /* CONFIG_ACPI */ 93 88 94 - r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, &add); 89 + r = HYPERVISOR_physdev_op(PHYSDEVOP_pci_device_add, add); 95 90 if (r != -ENOSYS) 96 91 return r; 97 92 pci_seg_supported = false;