Commit 19a519ca authored by Linus Torvalds's avatar Linus Torvalds

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

Pull xen updates from Juergen Gross:

 - fix a boot problem as a Xen dom0 on some AMD systems

 - fix Xen PVH boot problems with KASAN enabled

 - fix for a build warning

 - fixes to swiotlb-xen

* tag 'for-linus-6.12-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen/swiotlb: fix allocated size
  xen/swiotlb: add alignment check for dma buffers
  xen/pci: Avoid -Wflex-array-member-not-at-end warning
  xen/xenbus: Convert to use ERR_CAST()
  xen, pvh: fix unbootable VMs by inlining memset() in xen_prepare_pvh()
  x86/cpu: fix unbootable VMs by inlining memcmp() in hypervisor_cpuid_base()
  xen, pvh: fix unbootable VMs (PVH + KASAN - AMD_MEM_ENCRYPT)
  xen: tolerate ACPI NVS memory overlapping with Xen allocated memory
  xen: allow mapping ACPI data using a different physical address
  xen: add capability to remap non-RAM pages to different PFNs
  xen: move max_pfn in xen_memory_setup() out of function scope
  xen: move checks for e820 conflicts further up
  xen: introduce generic helper checking for memory map conflicts
  xen: use correct end address of kernel for conflict checking
parents 1d7bb2bf c3dea3d5
...@@ -174,6 +174,14 @@ void acpi_generic_reduced_hw_init(void); ...@@ -174,6 +174,14 @@ void acpi_generic_reduced_hw_init(void);
void x86_default_set_root_pointer(u64 addr); void x86_default_set_root_pointer(u64 addr);
u64 x86_default_get_root_pointer(void); u64 x86_default_get_root_pointer(void);
#ifdef CONFIG_XEN_PV
/* A Xen PV domain needs a special acpi_os_ioremap() handling. */
extern void __iomem * (*acpi_os_ioremap)(acpi_physical_address phys,
acpi_size size);
void __iomem *x86_acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
#define acpi_os_ioremap acpi_os_ioremap
#endif
#else /* !CONFIG_ACPI */ #else /* !CONFIG_ACPI */
#define acpi_lapic 0 #define acpi_lapic 0
......
...@@ -196,7 +196,12 @@ static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves) ...@@ -196,7 +196,12 @@ static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
for_each_possible_hypervisor_cpuid_base(base) { for_each_possible_hypervisor_cpuid_base(base) {
cpuid(base, &eax, &signature[0], &signature[1], &signature[2]); cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
if (!memcmp(sig, signature, 12) && /*
* This must not compile to "call memcmp" because it's called
* from PVH early boot code before instrumentation is set up
* and memcmp() itself may be instrumented.
*/
if (!__builtin_memcmp(sig, signature, 12) &&
(leaves == 0 || ((eax - base) >= leaves))) (leaves == 0 || ((eax - base) >= leaves)))
return base; return base;
} }
......
...@@ -1778,3 +1778,14 @@ u64 x86_default_get_root_pointer(void) ...@@ -1778,3 +1778,14 @@ u64 x86_default_get_root_pointer(void)
{ {
return boot_params.acpi_rsdp_addr; return boot_params.acpi_rsdp_addr;
} }
#ifdef CONFIG_XEN_PV
void __iomem *x86_acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
{
return ioremap_cache(phys, size);
}
void __iomem * (*acpi_os_ioremap)(acpi_physical_address phys, acpi_size size) =
x86_acpi_os_ioremap;
EXPORT_SYMBOL_GPL(acpi_os_ioremap);
#endif
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/acpi.h>
#include <asm/apic.h> #include <asm/apic.h>
#include <asm/io_apic.h> #include <asm/io_apic.h>
#include <asm/acpi.h> #include <asm/acpi.h>
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/range.h> #include <linux/range.h>
#include <linux/acpi.h>
#include <asm/pci-direct.h> #include <asm/pci-direct.h>
#include <linux/sort.h> #include <linux/sort.h>
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include <linux/stackprotector.h> #include <linux/stackprotector.h>
#include <linux/cpuhotplug.h> #include <linux/cpuhotplug.h>
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <linux/acpi.h>
#include <asm/acpi.h> #include <asm/acpi.h>
#include <asm/cacheinfo.h> #include <asm/cacheinfo.h>
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/acpi.h>
#include <asm/acpi.h> #include <asm/acpi.h>
#include <asm/bios_ebda.h> #include <asm/bios_ebda.h>
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
OBJECT_FILES_NON_STANDARD_head.o := y OBJECT_FILES_NON_STANDARD_head.o := y
KASAN_SANITIZE := n
obj-$(CONFIG_PVH) += enlighten.o obj-$(CONFIG_PVH) += enlighten.o
obj-$(CONFIG_PVH) += head.o obj-$(CONFIG_PVH) += head.o
...@@ -130,7 +130,11 @@ void __init xen_prepare_pvh(void) ...@@ -130,7 +130,11 @@ void __init xen_prepare_pvh(void)
BUG(); BUG();
} }
memset(&pvh_bootparams, 0, sizeof(pvh_bootparams)); /*
* This must not compile to "call memset" because memset() may be
* instrumented.
*/
__builtin_memset(&pvh_bootparams, 0, sizeof(pvh_bootparams));
hypervisor_specific_init(xen_guest); hypervisor_specific_init(xen_guest);
......
...@@ -2018,10 +2018,7 @@ void __init xen_reserve_special_pages(void) ...@@ -2018,10 +2018,7 @@ void __init xen_reserve_special_pages(void)
void __init xen_pt_check_e820(void) void __init xen_pt_check_e820(void)
{ {
if (xen_is_e820_reserved(xen_pt_base, xen_pt_size)) { xen_chk_is_e820_usable(xen_pt_base, xen_pt_size, "page table");
xen_raw_console_write("Xen hypervisor allocated page table memory conflicts with E820 map\n");
BUG();
}
} }
static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
......
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/acpi.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/setup.h> #include <asm/setup.h>
...@@ -80,6 +81,7 @@ ...@@ -80,6 +81,7 @@
#include <asm/xen/hypervisor.h> #include <asm/xen/hypervisor.h>
#include <xen/balloon.h> #include <xen/balloon.h>
#include <xen/grant_table.h> #include <xen/grant_table.h>
#include <xen/hvc-console.h>
#include "xen-ops.h" #include "xen-ops.h"
...@@ -792,6 +794,102 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, ...@@ -792,6 +794,102 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
return ret; return ret;
} }
/* Remapped non-RAM areas */
#define NR_NONRAM_REMAP 4
static struct nonram_remap {
phys_addr_t maddr;
phys_addr_t paddr;
size_t size;
} xen_nonram_remap[NR_NONRAM_REMAP] __ro_after_init;
static unsigned int nr_nonram_remap __ro_after_init;
/*
* Do the real remapping of non-RAM regions as specified in the
* xen_nonram_remap[] array.
* In case of an error just crash the system.
*/
void __init xen_do_remap_nonram(void)
{
unsigned int i;
unsigned int remapped = 0;
const struct nonram_remap *remap = xen_nonram_remap;
unsigned long pfn, mfn, end_pfn;
for (i = 0; i < nr_nonram_remap; i++) {
end_pfn = PFN_UP(remap->paddr + remap->size);
pfn = PFN_DOWN(remap->paddr);
mfn = PFN_DOWN(remap->maddr);
while (pfn < end_pfn) {
if (!set_phys_to_machine(pfn, mfn))
panic("Failed to set p2m mapping for pfn=%lx mfn=%lx\n",
pfn, mfn);
pfn++;
mfn++;
remapped++;
}
remap++;
}
pr_info("Remapped %u non-RAM page(s)\n", remapped);
}
#ifdef CONFIG_ACPI
/*
* Xen variant of acpi_os_ioremap() taking potentially remapped non-RAM
* regions into account.
* Any attempt to map an area crossing a remap boundary will produce a
* WARN() splat.
* phys is related to remap->maddr on input and will be rebased to remap->paddr.
*/
static void __iomem *xen_acpi_os_ioremap(acpi_physical_address phys,
acpi_size size)
{
unsigned int i;
const struct nonram_remap *remap = xen_nonram_remap;
for (i = 0; i < nr_nonram_remap; i++) {
if (phys + size > remap->maddr &&
phys < remap->maddr + remap->size) {
WARN_ON(phys < remap->maddr ||
phys + size > remap->maddr + remap->size);
phys += remap->paddr - remap->maddr;
break;
}
}
return x86_acpi_os_ioremap(phys, size);
}
#endif /* CONFIG_ACPI */
/*
* Add a new non-RAM remap entry.
* In case of no free entry found, just crash the system.
*/
void __init xen_add_remap_nonram(phys_addr_t maddr, phys_addr_t paddr,
unsigned long size)
{
BUG_ON((maddr & ~PAGE_MASK) != (paddr & ~PAGE_MASK));
if (nr_nonram_remap == NR_NONRAM_REMAP) {
xen_raw_console_write("Number of required E820 entry remapping actions exceed maximum value\n");
BUG();
}
#ifdef CONFIG_ACPI
/* Switch to the Xen acpi_os_ioremap() variant. */
if (nr_nonram_remap == 0)
acpi_os_ioremap = xen_acpi_os_ioremap;
#endif
xen_nonram_remap[nr_nonram_remap].maddr = maddr;
xen_nonram_remap[nr_nonram_remap].paddr = paddr;
xen_nonram_remap[nr_nonram_remap].size = size;
nr_nonram_remap++;
}
#ifdef CONFIG_XEN_DEBUG_FS #ifdef CONFIG_XEN_DEBUG_FS
#include <linux/debugfs.h> #include <linux/debugfs.h>
static int p2m_dump_show(struct seq_file *m, void *v) static int p2m_dump_show(struct seq_file *m, void *v)
......
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/memory_hotplug.h> #include <linux/memory_hotplug.h>
#include <linux/acpi.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/vdso.h> #include <asm/vdso.h>
#include <asm/e820/api.h> #include <asm/e820/api.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/acpi.h>
#include <asm/numa.h> #include <asm/numa.h>
#include <asm/idtentry.h> #include <asm/idtentry.h>
#include <asm/xen/hypervisor.h> #include <asm/xen/hypervisor.h>
...@@ -46,6 +46,9 @@ bool xen_pv_pci_possible; ...@@ -46,6 +46,9 @@ bool xen_pv_pci_possible;
/* E820 map used during setting up memory. */ /* E820 map used during setting up memory. */
static struct e820_table xen_e820_table __initdata; static struct e820_table xen_e820_table __initdata;
/* Number of initially usable memory pages. */
static unsigned long ini_nr_pages __initdata;
/* /*
* Buffer used to remap identity mapped pages. We only need the virtual space. * Buffer used to remap identity mapped pages. We only need the virtual space.
* The physical page behind this address is remapped as needed to different * The physical page behind this address is remapped as needed to different
...@@ -212,7 +215,7 @@ static int __init xen_free_mfn(unsigned long mfn) ...@@ -212,7 +215,7 @@ static int __init xen_free_mfn(unsigned long mfn)
* as a fallback if the remapping fails. * as a fallback if the remapping fails.
*/ */
static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn,
unsigned long end_pfn, unsigned long nr_pages) unsigned long end_pfn)
{ {
unsigned long pfn, end; unsigned long pfn, end;
int ret; int ret;
...@@ -220,7 +223,7 @@ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn, ...@@ -220,7 +223,7 @@ static void __init xen_set_identity_and_release_chunk(unsigned long start_pfn,
WARN_ON(start_pfn > end_pfn); WARN_ON(start_pfn > end_pfn);
/* Release pages first. */ /* Release pages first. */
end = min(end_pfn, nr_pages); end = min(end_pfn, ini_nr_pages);
for (pfn = start_pfn; pfn < end; pfn++) { for (pfn = start_pfn; pfn < end; pfn++) {
unsigned long mfn = pfn_to_mfn(pfn); unsigned long mfn = pfn_to_mfn(pfn);
...@@ -341,15 +344,14 @@ static void __init xen_do_set_identity_and_remap_chunk( ...@@ -341,15 +344,14 @@ static void __init xen_do_set_identity_and_remap_chunk(
* to Xen and not remapped. * to Xen and not remapped.
*/ */
static unsigned long __init xen_set_identity_and_remap_chunk( static unsigned long __init xen_set_identity_and_remap_chunk(
unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, unsigned long start_pfn, unsigned long end_pfn, unsigned long remap_pfn)
unsigned long remap_pfn)
{ {
unsigned long pfn; unsigned long pfn;
unsigned long i = 0; unsigned long i = 0;
unsigned long n = end_pfn - start_pfn; unsigned long n = end_pfn - start_pfn;
if (remap_pfn == 0) if (remap_pfn == 0)
remap_pfn = nr_pages; remap_pfn = ini_nr_pages;
while (i < n) { while (i < n) {
unsigned long cur_pfn = start_pfn + i; unsigned long cur_pfn = start_pfn + i;
...@@ -358,19 +360,19 @@ static unsigned long __init xen_set_identity_and_remap_chunk( ...@@ -358,19 +360,19 @@ static unsigned long __init xen_set_identity_and_remap_chunk(
unsigned long remap_range_size; unsigned long remap_range_size;
/* Do not remap pages beyond the current allocation */ /* Do not remap pages beyond the current allocation */
if (cur_pfn >= nr_pages) { if (cur_pfn >= ini_nr_pages) {
/* Identity map remaining pages */ /* Identity map remaining pages */
set_phys_range_identity(cur_pfn, cur_pfn + size); set_phys_range_identity(cur_pfn, cur_pfn + size);
break; break;
} }
if (cur_pfn + size > nr_pages) if (cur_pfn + size > ini_nr_pages)
size = nr_pages - cur_pfn; size = ini_nr_pages - cur_pfn;
remap_range_size = xen_find_pfn_range(&remap_pfn); remap_range_size = xen_find_pfn_range(&remap_pfn);
if (!remap_range_size) { if (!remap_range_size) {
pr_warn("Unable to find available pfn range, not remapping identity pages\n"); pr_warn("Unable to find available pfn range, not remapping identity pages\n");
xen_set_identity_and_release_chunk(cur_pfn, xen_set_identity_and_release_chunk(cur_pfn,
cur_pfn + left, nr_pages); cur_pfn + left);
break; break;
} }
/* Adjust size to fit in current e820 RAM region */ /* Adjust size to fit in current e820 RAM region */
...@@ -397,18 +399,18 @@ static unsigned long __init xen_set_identity_and_remap_chunk( ...@@ -397,18 +399,18 @@ static unsigned long __init xen_set_identity_and_remap_chunk(
} }
static unsigned long __init xen_count_remap_pages( static unsigned long __init xen_count_remap_pages(
unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages, unsigned long start_pfn, unsigned long end_pfn,
unsigned long remap_pages) unsigned long remap_pages)
{ {
if (start_pfn >= nr_pages) if (start_pfn >= ini_nr_pages)
return remap_pages; return remap_pages;
return remap_pages + min(end_pfn, nr_pages) - start_pfn; return remap_pages + min(end_pfn, ini_nr_pages) - start_pfn;
} }
static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, static unsigned long __init xen_foreach_remap_area(
unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn, unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn,
unsigned long nr_pages, unsigned long last_val)) unsigned long last_val))
{ {
phys_addr_t start = 0; phys_addr_t start = 0;
unsigned long ret_val = 0; unsigned long ret_val = 0;
...@@ -436,8 +438,7 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages, ...@@ -436,8 +438,7 @@ static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages,
end_pfn = PFN_UP(entry->addr); end_pfn = PFN_UP(entry->addr);
if (start_pfn < end_pfn) if (start_pfn < end_pfn)
ret_val = func(start_pfn, end_pfn, nr_pages, ret_val = func(start_pfn, end_pfn, ret_val);
ret_val);
start = end; start = end;
} }
} }
...@@ -494,6 +495,8 @@ void __init xen_remap_memory(void) ...@@ -494,6 +495,8 @@ void __init xen_remap_memory(void)
set_pte_mfn(buf, mfn_save, PAGE_KERNEL); set_pte_mfn(buf, mfn_save, PAGE_KERNEL);
pr_info("Remapped %ld page(s)\n", remapped); pr_info("Remapped %ld page(s)\n", remapped);
xen_do_remap_nonram();
} }
static unsigned long __init xen_get_pages_limit(void) static unsigned long __init xen_get_pages_limit(void)
...@@ -567,7 +570,7 @@ static void __init xen_ignore_unusable(void) ...@@ -567,7 +570,7 @@ static void __init xen_ignore_unusable(void)
} }
} }
bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size) static bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size)
{ {
struct e820_entry *entry; struct e820_entry *entry;
unsigned mapcnt; unsigned mapcnt;
...@@ -624,6 +627,111 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size) ...@@ -624,6 +627,111 @@ phys_addr_t __init xen_find_free_area(phys_addr_t size)
return 0; return 0;
} }
/*
* Swap a non-RAM E820 map entry with RAM above ini_nr_pages.
* Note that the E820 map is modified accordingly, but the P2M map isn't yet.
* The adaption of the P2M must be deferred until page allocation is possible.
*/
static void __init xen_e820_swap_entry_with_ram(struct e820_entry *swap_entry)
{
struct e820_entry *entry;
unsigned int mapcnt;
phys_addr_t mem_end = PFN_PHYS(ini_nr_pages);
phys_addr_t swap_addr, swap_size, entry_end;
swap_addr = PAGE_ALIGN_DOWN(swap_entry->addr);
swap_size = PAGE_ALIGN(swap_entry->addr - swap_addr + swap_entry->size);
entry = xen_e820_table.entries;
for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) {
entry_end = entry->addr + entry->size;
if (entry->type == E820_TYPE_RAM && entry->size >= swap_size &&
entry_end - swap_size >= mem_end) {
/* Reduce RAM entry by needed space (whole pages). */
entry->size -= swap_size;
/* Add new entry at the end of E820 map. */
entry = xen_e820_table.entries +
xen_e820_table.nr_entries;
xen_e820_table.nr_entries++;
/* Fill new entry (keep size and page offset). */
entry->type = swap_entry->type;
entry->addr = entry_end - swap_size +
swap_addr - swap_entry->addr;
entry->size = swap_entry->size;
/* Convert old entry to RAM, align to pages. */
swap_entry->type = E820_TYPE_RAM;
swap_entry->addr = swap_addr;
swap_entry->size = swap_size;
/* Remember PFN<->MFN relation for P2M update. */
xen_add_remap_nonram(swap_addr, entry_end - swap_size,
swap_size);
/* Order E820 table and merge entries. */
e820__update_table(&xen_e820_table);
return;
}
entry++;
}
xen_raw_console_write("No suitable area found for required E820 entry remapping action\n");
BUG();
}
/*
* Look for non-RAM memory types in a specific guest physical area and move
* those away if possible (ACPI NVS only for now).
*/
static void __init xen_e820_resolve_conflicts(phys_addr_t start,
phys_addr_t size)
{
struct e820_entry *entry;
unsigned int mapcnt;
phys_addr_t end;
if (!size)
return;
end = start + size;
entry = xen_e820_table.entries;
for (mapcnt = 0; mapcnt < xen_e820_table.nr_entries; mapcnt++) {
if (entry->addr >= end)
return;
if (entry->addr + entry->size > start &&
entry->type == E820_TYPE_NVS)
xen_e820_swap_entry_with_ram(entry);
entry++;
}
}
/*
* Check for an area in physical memory to be usable for non-movable purposes.
* An area is considered to usable if the used E820 map lists it to be RAM or
* some other type which can be moved to higher PFNs while keeping the MFNs.
* In case the area is not usable, crash the system with an error message.
*/
void __init xen_chk_is_e820_usable(phys_addr_t start, phys_addr_t size,
const char *component)
{
xen_e820_resolve_conflicts(start, size);
if (!xen_is_e820_reserved(start, size))
return;
xen_raw_console_write("Xen hypervisor allocated ");
xen_raw_console_write(component);
xen_raw_console_write(" memory conflicts with E820 map\n");
BUG();
}
/* /*
* Like memcpy, but with physical addresses for dest and src. * Like memcpy, but with physical addresses for dest and src.
*/ */
...@@ -683,7 +791,7 @@ static void __init xen_reserve_xen_mfnlist(void) ...@@ -683,7 +791,7 @@ static void __init xen_reserve_xen_mfnlist(void)
**/ **/
char * __init xen_memory_setup(void) char * __init xen_memory_setup(void)
{ {
unsigned long max_pfn, pfn_s, n_pfns; unsigned long pfn_s, n_pfns;
phys_addr_t mem_end, addr, size, chunk_size; phys_addr_t mem_end, addr, size, chunk_size;
u32 type; u32 type;
int rc; int rc;
...@@ -695,9 +803,8 @@ char * __init xen_memory_setup(void) ...@@ -695,9 +803,8 @@ char * __init xen_memory_setup(void)
int op; int op;
xen_parse_512gb(); xen_parse_512gb();
max_pfn = xen_get_pages_limit(); ini_nr_pages = min(xen_get_pages_limit(), xen_start_info->nr_pages);
max_pfn = min(max_pfn, xen_start_info->nr_pages); mem_end = PFN_PHYS(ini_nr_pages);
mem_end = PFN_PHYS(max_pfn);
memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries); memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries);
set_xen_guest_handle(memmap.buffer, xen_e820_table.entries); set_xen_guest_handle(memmap.buffer, xen_e820_table.entries);
...@@ -747,13 +854,35 @@ char * __init xen_memory_setup(void) ...@@ -747,13 +854,35 @@ char * __init xen_memory_setup(void)
/* Make sure the Xen-supplied memory map is well-ordered. */ /* Make sure the Xen-supplied memory map is well-ordered. */
e820__update_table(&xen_e820_table); e820__update_table(&xen_e820_table);
/*
* Check whether the kernel itself conflicts with the target E820 map.
* Failing now is better than running into weird problems later due
* to relocating (and even reusing) pages with kernel text or data.
*/
xen_chk_is_e820_usable(__pa_symbol(_text),
__pa_symbol(_end) - __pa_symbol(_text),
"kernel");
/*
* Check for a conflict of the xen_start_info memory with the target
* E820 map.
*/
xen_chk_is_e820_usable(__pa(xen_start_info), sizeof(*xen_start_info),
"xen_start_info");
/*
* Check for a conflict of the hypervisor supplied page tables with
* the target E820 map.
*/
xen_pt_check_e820();
max_pages = xen_get_max_pages(); max_pages = xen_get_max_pages();
/* How many extra pages do we need due to remapping? */ /* How many extra pages do we need due to remapping? */
max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages); max_pages += xen_foreach_remap_area(xen_count_remap_pages);
if (max_pages > max_pfn) if (max_pages > ini_nr_pages)
extra_pages += max_pages - max_pfn; extra_pages += max_pages - ini_nr_pages;
/* /*
* Clamp the amount of extra memory to a EXTRA_MEM_RATIO * Clamp the amount of extra memory to a EXTRA_MEM_RATIO
...@@ -762,8 +891,8 @@ char * __init xen_memory_setup(void) ...@@ -762,8 +891,8 @@ char * __init xen_memory_setup(void)
* Make sure we have no memory above max_pages, as this area * Make sure we have no memory above max_pages, as this area
* isn't handled by the p2m management. * isn't handled by the p2m management.
*/ */
maxmem_pages = EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)); maxmem_pages = EXTRA_MEM_RATIO * min(ini_nr_pages, PFN_DOWN(MAXMEM));
extra_pages = min3(maxmem_pages, extra_pages, max_pages - max_pfn); extra_pages = min3(maxmem_pages, extra_pages, max_pages - ini_nr_pages);
i = 0; i = 0;
addr = xen_e820_table.entries[0].addr; addr = xen_e820_table.entries[0].addr;
size = xen_e820_table.entries[0].size; size = xen_e820_table.entries[0].size;
...@@ -819,23 +948,6 @@ char * __init xen_memory_setup(void) ...@@ -819,23 +948,6 @@ char * __init xen_memory_setup(void)
e820__update_table(e820_table); e820__update_table(e820_table);
/*
* Check whether the kernel itself conflicts with the target E820 map.
* Failing now is better than running into weird problems later due
* to relocating (and even reusing) pages with kernel text or data.
*/
if (xen_is_e820_reserved(__pa_symbol(_text),
__pa_symbol(__bss_stop) - __pa_symbol(_text))) {
xen_raw_console_write("Xen hypervisor allocated kernel memory conflicts with E820 map\n");
BUG();
}
/*
* Check for a conflict of the hypervisor supplied page tables with
* the target E820 map.
*/
xen_pt_check_e820();
xen_reserve_xen_mfnlist(); xen_reserve_xen_mfnlist();
/* Check for a conflict of the initrd with the target E820 map. */ /* Check for a conflict of the initrd with the target E820 map. */
...@@ -863,7 +975,7 @@ char * __init xen_memory_setup(void) ...@@ -863,7 +975,7 @@ char * __init xen_memory_setup(void)
* Set identity map on non-RAM pages and prepare remapping the * Set identity map on non-RAM pages and prepare remapping the
* underlying RAM. * underlying RAM.
*/ */
xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk); xen_foreach_remap_area(xen_set_identity_and_remap_chunk);
pr_info("Released %ld page(s)\n", xen_released_pages); pr_info("Released %ld page(s)\n", xen_released_pages);
......
...@@ -47,8 +47,12 @@ void xen_mm_unpin_all(void); ...@@ -47,8 +47,12 @@ void xen_mm_unpin_all(void);
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
void __init xen_relocate_p2m(void); void __init xen_relocate_p2m(void);
#endif #endif
void __init xen_do_remap_nonram(void);
void __init xen_add_remap_nonram(phys_addr_t maddr, phys_addr_t paddr,
unsigned long size);
bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size); void __init xen_chk_is_e820_usable(phys_addr_t start, phys_addr_t size,
const char *component);
unsigned long __ref xen_chk_extra_mem(unsigned long pfn); unsigned long __ref xen_chk_extra_mem(unsigned long pfn);
void __init xen_inv_extra_mem(void); void __init xen_inv_extra_mem(void);
void __init xen_remap_memory(void); void __init xen_remap_memory(void);
......
...@@ -44,15 +44,11 @@ static int xen_add_device(struct device *dev) ...@@ -44,15 +44,11 @@ static int xen_add_device(struct device *dev)
} }
#endif #endif
if (pci_seg_supported) { if (pci_seg_supported) {
struct { DEFINE_RAW_FLEX(struct physdev_pci_device_add, add, optarr, 1);
struct physdev_pci_device_add add;
uint32_t pxm; add->seg = pci_domain_nr(pci_dev->bus);
} add_ext = { add->bus = pci_dev->bus->number;
.add.seg = pci_domain_nr(pci_dev->bus), add->devfn = pci_dev->devfn;
.add.bus = pci_dev->bus->number,
.add.devfn = pci_dev->devfn
};
struct physdev_pci_device_add *add = &add_ext.add;
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
acpi_handle handle; acpi_handle handle;
......
...@@ -78,9 +78,15 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size) ...@@ -78,9 +78,15 @@ static inline int range_straddles_page_boundary(phys_addr_t p, size_t size)
{ {
unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p); unsigned long next_bfn, xen_pfn = XEN_PFN_DOWN(p);
unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size); unsigned int i, nr_pages = XEN_PFN_UP(xen_offset_in_page(p) + size);
phys_addr_t algn = 1ULL << (get_order(size) + PAGE_SHIFT);
next_bfn = pfn_to_bfn(xen_pfn); next_bfn = pfn_to_bfn(xen_pfn);
/* If buffer is physically aligned, ensure DMA alignment. */
if (IS_ALIGNED(p, algn) &&
!IS_ALIGNED((phys_addr_t)next_bfn << XEN_PAGE_SHIFT, algn))
return 1;
for (i = 1; i < nr_pages; i++) for (i = 1; i < nr_pages; i++)
if (pfn_to_bfn(++xen_pfn) != ++next_bfn) if (pfn_to_bfn(++xen_pfn) != ++next_bfn)
return 1; return 1;
...@@ -141,7 +147,7 @@ xen_swiotlb_alloc_coherent(struct device *dev, size_t size, ...@@ -141,7 +147,7 @@ xen_swiotlb_alloc_coherent(struct device *dev, size_t size,
void *ret; void *ret;
/* Align the allocation to the Xen page size */ /* Align the allocation to the Xen page size */
size = 1UL << (order + XEN_PAGE_SHIFT); size = ALIGN(size, XEN_PAGE_SIZE);
ret = (void *)__get_free_pages(flags, get_order(size)); ret = (void *)__get_free_pages(flags, get_order(size));
if (!ret) if (!ret)
...@@ -173,7 +179,7 @@ xen_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr, ...@@ -173,7 +179,7 @@ xen_swiotlb_free_coherent(struct device *dev, size_t size, void *vaddr,
int order = get_order(size); int order = get_order(size);
/* Convert the size to actually allocated. */ /* Convert the size to actually allocated. */
size = 1UL << (order + XEN_PAGE_SHIFT); size = ALIGN(size, XEN_PAGE_SIZE);
if (WARN_ON_ONCE(dma_handle + size - 1 > dev->coherent_dma_mask) || if (WARN_ON_ONCE(dma_handle + size - 1 > dev->coherent_dma_mask) ||
WARN_ON_ONCE(range_straddles_page_boundary(phys, size))) WARN_ON_ONCE(range_straddles_page_boundary(phys, size)))
......
...@@ -427,12 +427,12 @@ char **xenbus_directory(struct xenbus_transaction t, ...@@ -427,12 +427,12 @@ char **xenbus_directory(struct xenbus_transaction t,
path = join(dir, node); path = join(dir, node);
if (IS_ERR(path)) if (IS_ERR(path))
return (char **)path; return ERR_CAST(path);
strings = xs_single(t, XS_DIRECTORY, path, &len); strings = xs_single(t, XS_DIRECTORY, path, &len);
kfree(path); kfree(path);
if (IS_ERR(strings)) if (IS_ERR(strings))
return (char **)strings; return ERR_CAST(strings);
return split(strings, len, num); return split(strings, len, num);
} }
...@@ -465,7 +465,7 @@ void *xenbus_read(struct xenbus_transaction t, ...@@ -465,7 +465,7 @@ void *xenbus_read(struct xenbus_transaction t,
path = join(dir, node); path = join(dir, node);
if (IS_ERR(path)) if (IS_ERR(path))
return (void *)path; return ERR_CAST(path);
ret = xs_single(t, XS_READ, path, len); ret = xs_single(t, XS_READ, path, len);
kfree(path); kfree(path);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment