Skip to content

Commit

Permalink
Merge tag 'stable/for-linus-3.19-rc4-tag' of git://git.kernel.org/pub…
Browse files Browse the repository at this point in the history
…/scm/linux/kernel/git/xen/tip

Pull xen bug fixes from David Vrabel:
 "Several critical linear p2m fixes that prevented some hosts from
  booting"

* tag 'stable/for-linus-3.19-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  x86/xen: properly retrieve NMI reason
  xen: check for zero sized area when invalidating memory
  xen: use correct type for physical addresses
  xen: correct race in alloc_p2m_pmd()
  xen: correct error for building p2m list on 32 bits
  x86/xen: avoid freeing static 'name' when kasprintf() fails
  x86/xen: add extra memory for remapped frames during setup
  x86/xen: don't count how many PFNs are identity mapped
  x86/xen: Free bootmem in free_p2m_page() during early boot
  x86/xen: Remove unnecessary BUG_ON(preemptible()) in xen_setup_timer()
  • Loading branch information
torvalds committed Jan 13, 2015
2 parents 4f7a42d + f221b04 commit 613d4ce
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 46 deletions.
22 changes: 21 additions & 1 deletion arch/x86/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <xen/interface/physdev.h>
#include <xen/interface/vcpu.h>
#include <xen/interface/memory.h>
#include <xen/interface/nmi.h>
#include <xen/interface/xen-mca.h>
#include <xen/features.h>
#include <xen/page.h>
Expand All @@ -66,6 +67,7 @@
#include <asm/reboot.h>
#include <asm/stackprotector.h>
#include <asm/hypervisor.h>
#include <asm/mach_traps.h>
#include <asm/mwait.h>
#include <asm/pci_x86.h>
#include <asm/pat.h>
Expand Down Expand Up @@ -1351,6 +1353,21 @@ static const struct machine_ops xen_machine_ops __initconst = {
.emergency_restart = xen_emergency_restart,
};

static unsigned char xen_get_nmi_reason(void)
{
unsigned char reason = 0;

/* Construct a value which looks like it came from port 0x61. */
if (test_bit(_XEN_NMIREASON_io_error,
&HYPERVISOR_shared_info->arch.nmi_reason))
reason |= NMI_REASON_IOCHK;
if (test_bit(_XEN_NMIREASON_pci_serr,
&HYPERVISOR_shared_info->arch.nmi_reason))
reason |= NMI_REASON_SERR;

return reason;
}

static void __init xen_boot_params_init_edd(void)
{
#if IS_ENABLED(CONFIG_EDD)
Expand Down Expand Up @@ -1535,9 +1552,12 @@ asmlinkage __visible void __init xen_start_kernel(void)
pv_info = xen_info;
pv_init_ops = xen_init_ops;
pv_apic_ops = xen_apic_ops;
if (!xen_pvh_domain())
if (!xen_pvh_domain()) {
pv_cpu_ops = xen_cpu_ops;

x86_platform.get_nmi_reason = xen_get_nmi_reason;
}

if (xen_feature(XENFEAT_auto_translated_physmap))
x86_init.resources.memory_setup = xen_auto_xlated_memory_setup;
else
Expand Down
20 changes: 10 additions & 10 deletions arch/x86/xen/p2m.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,13 @@ static void * __ref alloc_p2m_page(void)
return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
}

/* Only to be called in case of a race for a page just allocated! */
static void free_p2m_page(void *p)
static void __ref free_p2m_page(void *p)
{
BUG_ON(!slab_is_available());
if (unlikely(!slab_is_available())) {
free_bootmem((unsigned long)p, PAGE_SIZE);
return;
}

free_page((unsigned long)p);
}

Expand Down Expand Up @@ -375,7 +378,7 @@ static void __init xen_rebuild_p2m_list(unsigned long *p2m)
p2m_missing_pte : p2m_identity_pte;
for (i = 0; i < PMDS_PER_MID_PAGE; i++) {
pmdp = populate_extra_pmd(
(unsigned long)(p2m + pfn + i * PTRS_PER_PTE));
(unsigned long)(p2m + pfn) + i * PMD_SIZE);
set_pmd(pmdp, __pmd(__pa(ptep) | _KERNPG_TABLE));
}
}
Expand Down Expand Up @@ -436,10 +439,9 @@ EXPORT_SYMBOL_GPL(get_phys_to_machine);
* a new pmd is to replace p2m_missing_pte or p2m_identity_pte by a individual
* pmd. In case of PAE/x86-32 there are multiple pmds to allocate!
*/
static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *ptep, pte_t *pte_pg)
static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *pte_pg)
{
pte_t *ptechk;
pte_t *pteret = ptep;
pte_t *pte_newpg[PMDS_PER_MID_PAGE];
pmd_t *pmdp;
unsigned int level;
Expand Down Expand Up @@ -473,8 +475,6 @@ static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *ptep, pte_t *pte_pg)
if (ptechk == pte_pg) {
set_pmd(pmdp,
__pmd(__pa(pte_newpg[i]) | _KERNPG_TABLE));
if (vaddr == (addr & ~(PMD_SIZE - 1)))
pteret = pte_offset_kernel(pmdp, addr);
pte_newpg[i] = NULL;
}

Expand All @@ -488,7 +488,7 @@ static pte_t *alloc_p2m_pmd(unsigned long addr, pte_t *ptep, pte_t *pte_pg)
vaddr += PMD_SIZE;
}

return pteret;
return lookup_address(addr, &level);
}

/*
Expand Down Expand Up @@ -517,7 +517,7 @@ static bool alloc_p2m(unsigned long pfn)

if (pte_pg == p2m_missing_pte || pte_pg == p2m_identity_pte) {
/* PMD level is missing, allocate a new one */
ptep = alloc_p2m_pmd(addr, ptep, pte_pg);
ptep = alloc_p2m_pmd(addr, pte_pg);
if (!ptep)
return false;
}
Expand Down
42 changes: 20 additions & 22 deletions arch/x86/xen/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static void __init xen_del_extra_mem(u64 start, u64 size)
unsigned long __ref xen_chk_extra_mem(unsigned long pfn)
{
int i;
unsigned long addr = PFN_PHYS(pfn);
phys_addr_t addr = PFN_PHYS(pfn);

for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
if (addr >= xen_extra_mem[i].start &&
Expand All @@ -160,6 +160,8 @@ void __init xen_inv_extra_mem(void)
int i;

for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
if (!xen_extra_mem[i].size)
continue;
pfn_s = PFN_DOWN(xen_extra_mem[i].start);
pfn_e = PFN_UP(xen_extra_mem[i].start + xen_extra_mem[i].size);
for (pfn = pfn_s; pfn < pfn_e; pfn++)
Expand Down Expand Up @@ -229,15 +231,14 @@ static int __init xen_free_mfn(unsigned long mfn)
* as a fallback if the remapping fails.
*/
static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn,
unsigned long end_pfn, unsigned long nr_pages, unsigned long *identity,
unsigned long *released)
unsigned long end_pfn, unsigned long nr_pages, unsigned long *released)
{
unsigned long len = 0;
unsigned long pfn, end;
int ret;

WARN_ON(start_pfn > end_pfn);

/* Release pages first. */
end = min(end_pfn, nr_pages);
for (pfn = start_pfn; pfn < end; pfn++) {
unsigned long mfn = pfn_to_mfn(pfn);
Expand All @@ -250,16 +251,14 @@ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn,
WARN(ret != 1, "Failed to release pfn %lx err=%d\n", pfn, ret);

if (ret == 1) {
(*released)++;
if (!__set_phys_to_machine(pfn, INVALID_P2M_ENTRY))
break;
len++;
} else
break;
}

/* Need to release pages first */
*released += len;
*identity += set_phys_range_identity(start_pfn, end_pfn);
set_phys_range_identity(start_pfn, end_pfn);
}

/*
Expand Down Expand Up @@ -287,7 +286,7 @@ static void __init xen_update_mem_tables(unsigned long pfn, unsigned long mfn)
}

/* Update kernel mapping, but not for highmem. */
if ((pfn << PAGE_SHIFT) >= __pa(high_memory))
if (pfn >= PFN_UP(__pa(high_memory - 1)))
return;

if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT),
Expand Down Expand Up @@ -318,7 +317,6 @@ static void __init xen_do_set_identity_and_remap_chunk(
unsigned long ident_pfn_iter, remap_pfn_iter;
unsigned long ident_end_pfn = start_pfn + size;
unsigned long left = size;
unsigned long ident_cnt = 0;
unsigned int i, chunk;

WARN_ON(size == 0);
Expand Down Expand Up @@ -347,8 +345,7 @@ static void __init xen_do_set_identity_and_remap_chunk(
xen_remap_mfn = mfn;

/* Set identity map */
ident_cnt += set_phys_range_identity(ident_pfn_iter,
ident_pfn_iter + chunk);
set_phys_range_identity(ident_pfn_iter, ident_pfn_iter + chunk);

left -= chunk;
}
Expand All @@ -371,7 +368,7 @@ static void __init xen_do_set_identity_and_remap_chunk(
static unsigned long __init xen_set_identity_and_remap_chunk(
const struct e820entry *list, size_t map_size, unsigned long start_pfn,
unsigned long end_pfn, unsigned long nr_pages, unsigned long remap_pfn,
unsigned long *identity, unsigned long *released)
unsigned long *released, unsigned long *remapped)
{
unsigned long pfn;
unsigned long i = 0;
Expand All @@ -386,8 +383,7 @@ static unsigned long __init xen_set_identity_and_remap_chunk(
/* Do not remap pages beyond the current allocation */
if (cur_pfn >= nr_pages) {
/* Identity map remaining pages */
*identity += set_phys_range_identity(cur_pfn,
cur_pfn + size);
set_phys_range_identity(cur_pfn, cur_pfn + size);
break;
}
if (cur_pfn + size > nr_pages)
Expand All @@ -398,7 +394,7 @@ static unsigned long __init xen_set_identity_and_remap_chunk(
if (!remap_range_size) {
pr_warning("Unable to find available pfn range, not remapping identity pages\n");
xen_set_identity_and_release_chunk(cur_pfn,
cur_pfn + left, nr_pages, identity, released);
cur_pfn + left, nr_pages, released);
break;
}
/* Adjust size to fit in current e820 RAM region */
Expand All @@ -410,7 +406,7 @@ static unsigned long __init xen_set_identity_and_remap_chunk(
/* Update variables to reflect new mappings. */
i += size;
remap_pfn += size;
*identity += size;
*remapped += size;
}

/*
Expand All @@ -427,13 +423,13 @@ static unsigned long __init xen_set_identity_and_remap_chunk(

static void __init xen_set_identity_and_remap(
const struct e820entry *list, size_t map_size, unsigned long nr_pages,
unsigned long *released)
unsigned long *released, unsigned long *remapped)
{
phys_addr_t start = 0;
unsigned long identity = 0;
unsigned long last_pfn = nr_pages;
const struct e820entry *entry;
unsigned long num_released = 0;
unsigned long num_remapped = 0;
int i;

/*
Expand All @@ -460,14 +456,14 @@ static void __init xen_set_identity_and_remap(
last_pfn = xen_set_identity_and_remap_chunk(
list, map_size, start_pfn,
end_pfn, nr_pages, last_pfn,
&identity, &num_released);
&num_released, &num_remapped);
start = end;
}
}

*released = num_released;
*remapped = num_remapped;

pr_info("Set %ld page(s) to 1-1 mapping\n", identity);
pr_info("Released %ld page(s)\n", num_released);
}

Expand Down Expand Up @@ -586,6 +582,7 @@ char * __init xen_memory_setup(void)
struct xen_memory_map memmap;
unsigned long max_pages;
unsigned long extra_pages = 0;
unsigned long remapped_pages;
int i;
int op;

Expand Down Expand Up @@ -635,9 +632,10 @@ char * __init xen_memory_setup(void)
* underlying RAM.
*/
xen_set_identity_and_remap(map, memmap.nr_entries, max_pfn,
&xen_released_pages);
&xen_released_pages, &remapped_pages);

extra_pages += xen_released_pages;
extra_pages += remapped_pages;

/*
* Clamp the amount of extra memory to a EXTRA_MEM_RATIO
Expand Down
18 changes: 5 additions & 13 deletions arch/x86/xen/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ static const struct clock_event_device *xen_clockevent =

struct xen_clock_event_device {
struct clock_event_device evt;
char *name;
char name[16];
};
static DEFINE_PER_CPU(struct xen_clock_event_device, xen_clock_events) = { .evt.irq = -1 };

Expand Down Expand Up @@ -420,46 +420,38 @@ void xen_teardown_timer(int cpu)
if (evt->irq >= 0) {
unbind_from_irqhandler(evt->irq, NULL);
evt->irq = -1;
kfree(per_cpu(xen_clock_events, cpu).name);
per_cpu(xen_clock_events, cpu).name = NULL;
}
}

void xen_setup_timer(int cpu)
{
char *name;
struct clock_event_device *evt;
struct xen_clock_event_device *xevt = &per_cpu(xen_clock_events, cpu);
struct clock_event_device *evt = &xevt->evt;
int irq;

evt = &per_cpu(xen_clock_events, cpu).evt;
WARN(evt->irq >= 0, "IRQ%d for CPU%d is already allocated\n", evt->irq, cpu);
if (evt->irq >= 0)
xen_teardown_timer(cpu);

printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu);

name = kasprintf(GFP_KERNEL, "timer%d", cpu);
if (!name)
name = "<timer kasprintf failed>";
snprintf(xevt->name, sizeof(xevt->name), "timer%d", cpu);

irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER|
IRQF_FORCE_RESUME|IRQF_EARLY_RESUME,
name, NULL);
xevt->name, NULL);
(void)xen_set_irq_priority(irq, XEN_IRQ_PRIORITY_MAX);

memcpy(evt, xen_clockevent, sizeof(*evt));

evt->cpumask = cpumask_of(cpu);
evt->irq = irq;
per_cpu(xen_clock_events, cpu).name = name;
}


void xen_setup_cpu_clockevents(void)
{
BUG_ON(preemptible());

clockevents_register_device(this_cpu_ptr(&xen_clock_events.evt));
}

Expand Down
Loading

0 comments on commit 613d4ce

Please sign in to comment.