mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
xen: bug fixes for 4.7-rc4
- Fix x86 PV dom0 crash during early boot on some hardware. - Fix two pciback bugs affects certain devices. - Fix potential overflow when clearing page tables in x86 PV. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJXbTwWAAoJEFxbo/MsZsTRu7IH/1sAn6KFHfP2Px/Sydh/pxZH 0oOW+2aZLVqu8BRiHj6YeQVRuhzdIgSoU9wMmCFX7rz1m6gq4c60cJF/lKYmlbxp 0lyxbf+4451rh/qNVV3pm5J+w6R818Y2hoIOu2BK3ppJ4W8nXbW5kHHvtYQCXu0A mApSgMHBbWv6kkAxEuUMa5wOipENiAIYg+pFqwo+y9V8sS8zAqqHivct3T6ucNyV u/WB076QAnL8abcwKELXsyV5hmcfJv/CoMS9Qv6GwIv1z9d0UVS2+qoo1Qox2sAP 79AoJn2E6p7rkb/HdhdSYjja22oct1ahrfSgCSBEwLNZCMc5srKdwK6Zspe5y+0= =qqrC -----END PGP SIGNATURE----- Merge tag 'for-linus-4.7b-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip Pull xen bug fixes from David Vrabel: - fix x86 PV dom0 crash during early boot on some hardware - fix two pciback bugs affects certain devices - fix potential overflow when clearing page tables in x86 PV * tag 'for-linus-4.7b-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: xen-pciback: return proper values during BAR sizing x86/xen: avoid m2p lookup when setting early page table entries xen/pciback: Fix conf_space read/write overlap check. x86/xen: fix upper bound of pmd loop in xen_cleanhighmap() xen/balloon: Fix declared-but-not-defined warning
This commit is contained in:
commit
032fd3e58c
@ -1113,7 +1113,7 @@ static void __init xen_cleanhighmap(unsigned long vaddr,
|
||||
|
||||
/* NOTE: The loop is more greedy than the cleanup_highmap variant.
|
||||
* We include the PMD passed in on _both_ boundaries. */
|
||||
for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PAGE_SIZE));
|
||||
for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PTRS_PER_PMD));
|
||||
pmd++, vaddr += PMD_SIZE) {
|
||||
if (pmd_none(*pmd))
|
||||
continue;
|
||||
@ -1551,41 +1551,6 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
/* If there's an existing pte, then don't allow _PAGE_RW to be set */
|
||||
if (pte_val_ma(*ptep) & _PAGE_PRESENT)
|
||||
pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
|
||||
pte_val_ma(pte));
|
||||
|
||||
return pte;
|
||||
}
|
||||
#else /* CONFIG_X86_64 */
|
||||
static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
unsigned long pfn;
|
||||
|
||||
if (xen_feature(XENFEAT_writable_page_tables) ||
|
||||
xen_feature(XENFEAT_auto_translated_physmap) ||
|
||||
xen_start_info->mfn_list >= __START_KERNEL_map)
|
||||
return pte;
|
||||
|
||||
/*
|
||||
* Pages belonging to the initial p2m list mapped outside the default
|
||||
* address range must be mapped read-only. This region contains the
|
||||
* page tables for mapping the p2m list, too, and page tables MUST be
|
||||
* mapped read-only.
|
||||
*/
|
||||
pfn = pte_pfn(pte);
|
||||
if (pfn >= xen_start_info->first_p2m_pfn &&
|
||||
pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames)
|
||||
pte = __pte_ma(pte_val_ma(pte) & ~_PAGE_RW);
|
||||
|
||||
return pte;
|
||||
}
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
/*
|
||||
* Init-time set_pte while constructing initial pagetables, which
|
||||
* doesn't allow RO page table pages to be remapped RW.
|
||||
@ -1600,13 +1565,37 @@ static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
|
||||
* so always write the PTE directly and rely on Xen trapping and
|
||||
* emulating any updates as necessary.
|
||||
*/
|
||||
__visible pte_t xen_make_pte_init(pteval_t pte)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
unsigned long pfn;
|
||||
|
||||
/*
|
||||
* Pages belonging to the initial p2m list mapped outside the default
|
||||
* address range must be mapped read-only. This region contains the
|
||||
* page tables for mapping the p2m list, too, and page tables MUST be
|
||||
* mapped read-only.
|
||||
*/
|
||||
pfn = (pte & PTE_PFN_MASK) >> PAGE_SHIFT;
|
||||
if (xen_start_info->mfn_list < __START_KERNEL_map &&
|
||||
pfn >= xen_start_info->first_p2m_pfn &&
|
||||
pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames)
|
||||
pte &= ~_PAGE_RW;
|
||||
#endif
|
||||
pte = pte_pfn_to_mfn(pte);
|
||||
return native_make_pte(pte);
|
||||
}
|
||||
PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_init);
|
||||
|
||||
static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
|
||||
{
|
||||
if (pte_mfn(pte) != INVALID_P2M_ENTRY)
|
||||
pte = mask_rw_pte(ptep, pte);
|
||||
else
|
||||
pte = __pte_ma(0);
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/* If there's an existing pte, then don't allow _PAGE_RW to be set */
|
||||
if (pte_mfn(pte) != INVALID_P2M_ENTRY
|
||||
&& pte_val_ma(*ptep) & _PAGE_PRESENT)
|
||||
pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
|
||||
pte_val_ma(pte));
|
||||
#endif
|
||||
native_set_pte(ptep, pte);
|
||||
}
|
||||
|
||||
@ -2407,6 +2396,7 @@ static void __init xen_post_allocator_init(void)
|
||||
pv_mmu_ops.alloc_pud = xen_alloc_pud;
|
||||
pv_mmu_ops.release_pud = xen_release_pud;
|
||||
#endif
|
||||
pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte);
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
pv_mmu_ops.write_cr3 = &xen_write_cr3;
|
||||
@ -2455,7 +2445,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
|
||||
.pte_val = PV_CALLEE_SAVE(xen_pte_val),
|
||||
.pgd_val = PV_CALLEE_SAVE(xen_pgd_val),
|
||||
|
||||
.make_pte = PV_CALLEE_SAVE(xen_make_pte),
|
||||
.make_pte = PV_CALLEE_SAVE(xen_make_pte_init),
|
||||
.make_pgd = PV_CALLEE_SAVE(xen_make_pgd),
|
||||
|
||||
#ifdef CONFIG_X86_PAE
|
||||
|
@ -151,8 +151,6 @@ static DECLARE_WAIT_QUEUE_HEAD(balloon_wq);
|
||||
static void balloon_process(struct work_struct *work);
|
||||
static DECLARE_DELAYED_WORK(balloon_worker, balloon_process);
|
||||
|
||||
static void release_memory_resource(struct resource *resource);
|
||||
|
||||
/* When ballooning out (allocating memory to return to Xen) we don't really
|
||||
want the kernel to try too hard since that can trigger the oom killer. */
|
||||
#define GFP_BALLOON \
|
||||
@ -248,6 +246,19 @@ static enum bp_state update_schedule(enum bp_state state)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
|
||||
static void release_memory_resource(struct resource *resource)
|
||||
{
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
/*
|
||||
* No need to reset region to identity mapped since we now
|
||||
* know that no I/O can be in this region
|
||||
*/
|
||||
release_resource(resource);
|
||||
kfree(resource);
|
||||
}
|
||||
|
||||
static struct resource *additional_memory_resource(phys_addr_t size)
|
||||
{
|
||||
struct resource *res;
|
||||
@ -286,19 +297,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)
|
||||
return res;
|
||||
}
|
||||
|
||||
static void release_memory_resource(struct resource *resource)
|
||||
{
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
/*
|
||||
* No need to reset region to identity mapped since we now
|
||||
* know that no I/O can be in this region
|
||||
*/
|
||||
release_resource(resource);
|
||||
kfree(resource);
|
||||
}
|
||||
|
||||
static enum bp_state reserve_additional_memory(void)
|
||||
{
|
||||
long credit;
|
||||
|
@ -183,8 +183,7 @@ int xen_pcibk_config_read(struct pci_dev *dev, int offset, int size,
|
||||
field_start = OFFSET(cfg_entry);
|
||||
field_end = OFFSET(cfg_entry) + field->size;
|
||||
|
||||
if ((req_start >= field_start && req_start < field_end)
|
||||
|| (req_end > field_start && req_end <= field_end)) {
|
||||
if (req_end > field_start && field_end > req_start) {
|
||||
err = conf_space_read(dev, cfg_entry, field_start,
|
||||
&tmp_val);
|
||||
if (err)
|
||||
@ -230,8 +229,7 @@ int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
|
||||
field_start = OFFSET(cfg_entry);
|
||||
field_end = OFFSET(cfg_entry) + field->size;
|
||||
|
||||
if ((req_start >= field_start && req_start < field_end)
|
||||
|| (req_end > field_start && req_end <= field_end)) {
|
||||
if (req_end > field_start && field_end > req_start) {
|
||||
tmp_val = 0;
|
||||
|
||||
err = xen_pcibk_config_read(dev, field_start,
|
||||
|
@ -145,7 +145,7 @@ static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
|
||||
/* A write to obtain the length must happen as a 32-bit write.
|
||||
* This does not (yet) support writing individual bytes
|
||||
*/
|
||||
if (value == ~PCI_ROM_ADDRESS_ENABLE)
|
||||
if ((value | ~PCI_ROM_ADDRESS_MASK) == ~0U)
|
||||
bar->which = 1;
|
||||
else {
|
||||
u32 tmpval;
|
||||
@ -225,38 +225,42 @@ static inline void read_dev_bar(struct pci_dev *dev,
|
||||
(PCI_BASE_ADDRESS_SPACE_MEMORY |
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64))) {
|
||||
bar_info->val = res[pos - 1].start >> 32;
|
||||
bar_info->len_val = res[pos - 1].end >> 32;
|
||||
bar_info->len_val = -resource_size(&res[pos - 1]) >> 32;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!res[pos].flags ||
|
||||
(res[pos].flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET |
|
||||
IORESOURCE_BUSY)))
|
||||
return;
|
||||
|
||||
bar_info->val = res[pos].start |
|
||||
(res[pos].flags & PCI_REGION_FLAG_MASK);
|
||||
bar_info->len_val = resource_size(&res[pos]);
|
||||
bar_info->len_val = -resource_size(&res[pos]) |
|
||||
(res[pos].flags & PCI_REGION_FLAG_MASK);
|
||||
}
|
||||
|
||||
static void *bar_init(struct pci_dev *dev, int offset)
|
||||
{
|
||||
struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
|
||||
struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
|
||||
|
||||
if (!bar)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
read_dev_bar(dev, bar, offset, ~0);
|
||||
bar->which = 0;
|
||||
|
||||
return bar;
|
||||
}
|
||||
|
||||
static void *rom_init(struct pci_dev *dev, int offset)
|
||||
{
|
||||
struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
|
||||
struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
|
||||
|
||||
if (!bar)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
|
||||
bar->which = 0;
|
||||
|
||||
return bar;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user