Commit 3946b46c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-5.15b-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull xen fixes from Juergen Gross:

 - fix two minor issues in the Xen privcmd driver plus a cleanup patch
   for that driver

 - fix multiple issues related to running as PVH guest and some related
   earlyprintk fixes for other Xen guest types

 - fix an issue introduced in 5.15 the Xen balloon driver

* tag 'for-linus-5.15b-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen/balloon: fix cancelled balloon action
  xen/x86: adjust data placement
  x86/PVH: adjust function/data placement
  xen/x86: hook up xen_banner() also for PVH
  xen/x86: generalize preferred console model from PV to PVH Dom0
  xen/x86: make "earlyprintk=xen" work for HVM/PVH DomU
  xen/x86: allow "earlyprintk=xen" to work for PV Dom0
  xen/x86: make "earlyprintk=xen" work better for PVH Dom0
  xen/x86: allow PVH Dom0 without XEN_PV=y
  xen/x86: prevent PVH type from getting clobbered
  xen/privcmd: drop "pages" parameter from xen_remap_pfn()
  xen/privcmd: fix error handling in mmap-resource processing
  xen/privcmd: replace kcalloc() by kvcalloc() when allocating empty pages
parents 0dcf60d0 319933a8
......@@ -1266,7 +1266,7 @@
The VGA and EFI output is eventually overwritten by
the real console.
The xen output can only be used by Xen PV guests.
The xen option can only be used in Xen domains.
The sclp output can only be used on s390.
......
......@@ -14,16 +14,19 @@ static inline int pci_xen_hvm_init(void)
return -1;
}
#endif
#if defined(CONFIG_XEN_DOM0)
#ifdef CONFIG_XEN_PV_DOM0
int __init pci_xen_initial_domain(void);
int xen_find_device_domain_owner(struct pci_dev *dev);
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
int xen_unregister_device_domain_owner(struct pci_dev *dev);
#else
static inline int __init pci_xen_initial_domain(void)
{
return -1;
}
#endif
#ifdef CONFIG_XEN_DOM0
int xen_find_device_domain_owner(struct pci_dev *dev);
int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
int xen_unregister_device_domain_owner(struct pci_dev *dev);
#else
static inline int xen_find_device_domain_owner(struct pci_dev *dev)
{
return -1;
......
......@@ -113,7 +113,7 @@ static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
false /* no mapping of GSI to PIRQ */);
}
#ifdef CONFIG_XEN_DOM0
#ifdef CONFIG_XEN_PV_DOM0
static int xen_register_gsi(u32 gsi, int triggering, int polarity)
{
int rc, irq;
......@@ -261,7 +261,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
return irq;
}
#ifdef CONFIG_XEN_DOM0
#ifdef CONFIG_XEN_PV_DOM0
static bool __read_mostly pci_seg_supported = true;
static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
......@@ -375,10 +375,10 @@ static void xen_initdom_restore_msi_irqs(struct pci_dev *dev)
WARN(ret && ret != -ENOSYS, "restore_msi -> %d\n", ret);
}
}
#else /* CONFIG_XEN_DOM0 */
#else /* CONFIG_XEN_PV_DOM0 */
#define xen_initdom_setup_msi_irqs NULL
#define xen_initdom_restore_msi_irqs NULL
#endif /* !CONFIG_XEN_DOM0 */
#endif /* !CONFIG_XEN_PV_DOM0 */
static void xen_teardown_msi_irqs(struct pci_dev *dev)
{
......@@ -555,7 +555,7 @@ int __init pci_xen_hvm_init(void)
return 0;
}
#ifdef CONFIG_XEN_DOM0
#ifdef CONFIG_XEN_PV_DOM0
int __init pci_xen_initial_domain(void)
{
int irq;
......@@ -583,6 +583,9 @@ int __init pci_xen_initial_domain(void)
}
return 0;
}
#endif
#ifdef CONFIG_XEN_DOM0
struct xen_device_domain_owner {
domid_t domain;
......@@ -656,4 +659,4 @@ int xen_unregister_device_domain_owner(struct pci_dev *dev)
return 0;
}
EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
#endif
#endif /* CONFIG_XEN_DOM0 */
......@@ -16,15 +16,15 @@
/*
* PVH variables.
*
* pvh_bootparams and pvh_start_info need to live in the data segment since
* pvh_bootparams and pvh_start_info need to live in a data segment since
* they are used after startup_{32|64}, which clear .bss, are invoked.
*/
struct boot_params pvh_bootparams __section(".data");
struct hvm_start_info pvh_start_info __section(".data");
struct boot_params __initdata pvh_bootparams;
struct hvm_start_info __initdata pvh_start_info;
unsigned int pvh_start_info_sz = sizeof(pvh_start_info);
const unsigned int __initconst pvh_start_info_sz = sizeof(pvh_start_info);
static u64 pvh_get_root_pointer(void)
static u64 __init pvh_get_root_pointer(void)
{
return pvh_start_info.rsdp_paddr;
}
......@@ -107,7 +107,7 @@ void __init __weak xen_pvh_init(struct boot_params *boot_params)
BUG();
}
static void hypervisor_specific_init(bool xen_guest)
static void __init hypervisor_specific_init(bool xen_guest)
{
if (xen_guest)
xen_pvh_init(&pvh_bootparams);
......
......@@ -43,13 +43,9 @@ config XEN_PV_SMP
def_bool y
depends on XEN_PV && SMP
config XEN_DOM0
bool "Xen PV Dom0 support"
default y
depends on XEN_PV && PCI_XEN && SWIOTLB_XEN
depends on X86_IO_APIC && ACPI && PCI
help
Support running as a Xen PV Dom0 guest.
config XEN_PV_DOM0
def_bool y
depends on XEN_PV && XEN_DOM0
config XEN_PVHVM
def_bool y
......@@ -86,3 +82,12 @@ config XEN_PVH
def_bool n
help
Support for running as a Xen PVH guest.
config XEN_DOM0
bool "Xen Dom0 support"
default XEN_PV
depends on (XEN_PV && SWIOTLB_XEN) || (XEN_PVH && X86_64)
depends on X86_IO_APIC && ACPI && PCI
select X86_X2APIC if XEN_PVH && X86_64
help
Support running as a Xen Dom0 guest.
......@@ -45,7 +45,7 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
obj-$(CONFIG_XEN_DOM0) += vga.o
obj-$(CONFIG_XEN_PV_DOM0) += vga.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
......
......@@ -3,6 +3,7 @@
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
#include <linux/memblock.h>
#endif
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/kexec.h>
#include <linux/slab.h>
......@@ -10,12 +11,15 @@
#include <xen/xen.h>
#include <xen/features.h>
#include <xen/interface/sched.h>
#include <xen/interface/version.h>
#include <xen/page.h>
#include <asm/xen/hypercall.h>
#include <asm/xen/hypervisor.h>
#include <asm/cpu.h>
#include <asm/e820/api.h>
#include <asm/setup.h>
#include "xen-ops.h"
#include "smp.h"
......@@ -52,9 +56,6 @@ DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
DEFINE_PER_CPU(uint32_t, xen_vcpu_id);
EXPORT_PER_CPU_SYMBOL(xen_vcpu_id);
enum xen_domain_type xen_domain_type = XEN_NATIVE;
EXPORT_SYMBOL_GPL(xen_domain_type);
unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
EXPORT_SYMBOL(machine_to_phys_mapping);
unsigned long machine_to_phys_nr;
......@@ -69,10 +70,12 @@ __read_mostly int xen_have_vector_callback;
EXPORT_SYMBOL_GPL(xen_have_vector_callback);
/*
* NB: needs to live in .data because it's used by xen_prepare_pvh which runs
* before clearing the bss.
* NB: These need to live in .data or alike because they're used by
* xen_prepare_pvh() which runs before clearing the bss.
*/
uint32_t xen_start_flags __section(".data") = 0;
enum xen_domain_type __ro_after_init xen_domain_type = XEN_NATIVE;
EXPORT_SYMBOL_GPL(xen_domain_type);
uint32_t __ro_after_init xen_start_flags;
EXPORT_SYMBOL(xen_start_flags);
/*
......@@ -258,6 +261,45 @@ int xen_vcpu_setup(int cpu)
return ((per_cpu(xen_vcpu, cpu) == NULL) ? -ENODEV : 0);
}
void __init xen_banner(void)
{
unsigned version = HYPERVISOR_xen_version(XENVER_version, NULL);
struct xen_extraversion extra;
HYPERVISOR_xen_version(XENVER_extraversion, &extra);
pr_info("Booting kernel on %s\n", pv_info.name);
pr_info("Xen version: %u.%u%s%s\n",
version >> 16, version & 0xffff, extra.extraversion,
xen_feature(XENFEAT_mmu_pt_update_preserve_ad)
? " (preserve-AD)" : "");
}
/* Check if running on Xen version (major, minor) or later */
bool xen_running_on_version_or_later(unsigned int major, unsigned int minor)
{
unsigned int version;
if (!xen_domain())
return false;
version = HYPERVISOR_xen_version(XENVER_version, NULL);
if ((((version >> 16) == major) && ((version & 0xffff) >= minor)) ||
((version >> 16) > major))
return true;
return false;
}
void __init xen_add_preferred_consoles(void)
{
add_preferred_console("xenboot", 0, NULL);
if (!boot_params.screen_info.orig_video_isVGA)
add_preferred_console("tty", 0, NULL);
add_preferred_console("hvc", 0, NULL);
if (boot_params.screen_info.orig_video_isVGA)
add_preferred_console("tty", 0, NULL);
}
void xen_reboot(int reason)
{
struct sched_shutdown r = { .reason = reason };
......
......@@ -28,7 +28,6 @@
#include <linux/mm.h>
#include <linux/page-flags.h>
#include <linux/highmem.h>
#include <linux/console.h>
#include <linux/pci.h>
#include <linux/gfp.h>
#include <linux/edd.h>
......@@ -109,17 +108,6 @@ struct tls_descs {
*/
static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc);
static void __init xen_banner(void)
{
unsigned version = HYPERVISOR_xen_version(XENVER_version, NULL);
struct xen_extraversion extra;
HYPERVISOR_xen_version(XENVER_extraversion, &extra);
pr_info("Booting paravirtualized kernel on %s\n", pv_info.name);
pr_info("Xen version: %d.%d%s (preserve-AD)\n",
version >> 16, version & 0xffff, extra.extraversion);
}
static void __init xen_pv_init_platform(void)
{
populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP));
......@@ -142,22 +130,6 @@ static void __init xen_pv_guest_late_init(void)
#endif
}
/* Check if running on Xen version (major, minor) or later */
bool
xen_running_on_version_or_later(unsigned int major, unsigned int minor)
{
unsigned int version;
if (!xen_domain())
return false;
version = HYPERVISOR_xen_version(XENVER_version, NULL);
if ((((version >> 16) == major) && ((version & 0xffff) >= minor)) ||
((version >> 16) > major))
return true;
return false;
}
static __read_mostly unsigned int cpuid_leaf5_ecx_val;
static __read_mostly unsigned int cpuid_leaf5_edx_val;
......@@ -1364,7 +1336,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
if (!xen_initial_domain()) {
add_preferred_console("xenboot", 0, NULL);
if (pci_xen)
x86_init.pci.arch_init = pci_xen_init;
x86_platform.set_legacy_features =
......@@ -1409,11 +1380,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
#endif
}
if (!boot_params.screen_info.orig_video_isVGA)
add_preferred_console("tty", 0, NULL);
add_preferred_console("hvc", 0, NULL);
if (boot_params.screen_info.orig_video_isVGA)
add_preferred_console("tty", 0, NULL);
xen_add_preferred_consoles();
#ifdef CONFIG_PCI
/* PCI BIOS service won't work from a PV guest. */
......
// SPDX-License-Identifier: GPL-2.0
#include <linux/acpi.h>
#include <linux/export.h>
#include <xen/hvc-console.h>
......@@ -18,10 +19,11 @@
/*
* PVH variables.
*
* The variable xen_pvh needs to live in the data segment since it is used
* The variable xen_pvh needs to live in a data segment since it is used
* after startup_{32|64} is invoked, which will clear the .bss segment.
*/
bool xen_pvh __section(".data") = 0;
bool __ro_after_init xen_pvh;
EXPORT_SYMBOL_GPL(xen_pvh);
void __init xen_pvh_init(struct boot_params *boot_params)
{
......@@ -36,6 +38,10 @@ void __init xen_pvh_init(struct boot_params *boot_params)
pfn = __pa(hypercall_page);
wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
if (xen_initial_domain())
x86_init.oem.arch_setup = xen_add_preferred_consoles;
x86_init.oem.banner = xen_banner;
xen_efi_init(boot_params);
}
......
......@@ -2398,7 +2398,7 @@ static int remap_area_pfn_pte_fn(pte_t *ptep, unsigned long addr, void *data)
int xen_remap_pfn(struct vm_area_struct *vma, unsigned long addr,
xen_pfn_t *pfn, int nr, int *err_ptr, pgprot_t prot,
unsigned int domid, bool no_translate, struct page **pages)
unsigned int domid, bool no_translate)
{
int err = 0;
struct remap_data rmd;
......
......@@ -51,6 +51,7 @@ void __init xen_remap_memory(void);
phys_addr_t __init xen_find_free_area(phys_addr_t size);
char * __init xen_memory_setup(void);
void __init xen_arch_setup(void);
void xen_banner(void);
void xen_enable_sysenter(void);
void xen_enable_syscall(void);
void xen_vcpu_restore(void);
......@@ -109,7 +110,7 @@ static inline void xen_uninit_lock_cpu(int cpu)
struct dom0_vga_console_info;
#ifdef CONFIG_XEN_DOM0
#ifdef CONFIG_XEN_PV_DOM0
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
#else
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
......@@ -118,6 +119,8 @@ static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
}
#endif
void xen_add_preferred_consoles(void);
void __init xen_init_apic(void);
#ifdef CONFIG_XEN_EFI
......
......@@ -618,10 +618,8 @@ static int __init xenboot_console_setup(struct console *console, char *string)
{
static struct xencons_info xenboot;
if (xen_initial_domain())
if (xen_initial_domain() || !xen_pv_domain())
return 0;
if (!xen_pv_domain())
return -ENODEV;
return xencons_info_pv_init(&xenboot, 0);
}
......@@ -632,17 +630,16 @@ static void xenboot_write_console(struct console *console, const char *string,
unsigned int linelen, off = 0;
const char *pos;
if (dom0_write_console(0, string, len) >= 0)
return;
if (!xen_pv_domain()) {
xen_hvm_early_write(0, string, len);
return;
}
dom0_write_console(0, string, len);
if (xen_initial_domain())
if (domU_write_console(0, "(early) ", 8) < 0)
return;
domU_write_console(0, "(early) ", 8);
while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
linelen = pos-string+off;
if (off + linelen > len)
......
......@@ -241,7 +241,7 @@ config XEN_PRIVCMD
config XEN_ACPI_PROCESSOR
tristate "Xen ACPI processor"
depends on XEN && XEN_DOM0 && X86 && ACPI_PROCESSOR && CPU_FREQ
depends on XEN && XEN_PV_DOM0 && X86 && ACPI_PROCESSOR && CPU_FREQ
default m
help
This ACPI processor uploads Power Management information to the Xen
......@@ -259,7 +259,7 @@ config XEN_ACPI_PROCESSOR
config XEN_MCE_LOG
bool "Xen platform mcelog"
depends on XEN_DOM0 && X86_MCE
depends on XEN_PV_DOM0 && X86_MCE
help
Allow kernel fetching MCE error from Xen platform and
converting it into Linux mcelog format for mcelog tools
......
......@@ -491,12 +491,12 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
}
/*
* Stop waiting if either state is not BP_EAGAIN and ballooning action is
* needed, or if the credit has changed while state is BP_EAGAIN.
* Stop waiting if either state is BP_DONE and ballooning action is
* needed, or if the credit has changed while state is not BP_DONE.
*/
static bool balloon_thread_cond(enum bp_state state, long credit)
{
if (state != BP_EAGAIN)
if (state == BP_DONE)
credit = 0;
return current_credit() != credit || kthread_should_stop();
......@@ -516,10 +516,19 @@ static int balloon_thread(void *unused)
set_freezable();
for (;;) {
if (state == BP_EAGAIN)
timeout = balloon_stats.schedule_delay * HZ;
else
switch (state) {
case BP_DONE:
case BP_ECANCELED:
timeout = 3600 * HZ;
break;
case BP_EAGAIN:
timeout = balloon_stats.schedule_delay * HZ;
break;
case BP_WAIT:
timeout = HZ;
break;
}
credit = current_credit();
wait_event_freezable_timeout(balloon_thread_wq,
......
......@@ -257,7 +257,7 @@ static long privcmd_ioctl_mmap(struct file *file, void __user *udata)
LIST_HEAD(pagelist);
struct mmap_gfn_state state;
/* We only support privcmd_ioctl_mmap_batch for auto translated. */
/* We only support privcmd_ioctl_mmap_batch for non-auto-translated. */
if (xen_feature(XENFEAT_auto_translated_physmap))
return -ENOSYS;
......@@ -420,7 +420,7 @@ static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs)
int rc;
struct page **pages;
pages = kcalloc(numpgs, sizeof(pages[0]), GFP_KERNEL);
pages = kvcalloc(numpgs, sizeof(pages[0]), GFP_KERNEL);
if (pages == NULL)
return -ENOMEM;
......@@ -428,7 +428,7 @@ static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs)
if (rc != 0) {
pr_warn("%s Could not alloc %d pfns rc:%d\n", __func__,
numpgs, rc);
kfree(pages);
kvfree(pages);
return -ENOMEM;
}
BUG_ON(vma->vm_private_data != NULL);
......@@ -803,21 +803,21 @@ static long privcmd_ioctl_mmap_resource(struct file *file,
unsigned int domid =
(xdata.flags & XENMEM_rsrc_acq_caller_owned) ?
DOMID_SELF : kdata.dom;
int num;
int num, *errs = (int *)pfns;
BUILD_BUG_ON(sizeof(*errs) > sizeof(*pfns));
num = xen_remap_domain_mfn_array(vma,
kdata.addr & PAGE_MASK,
pfns, kdata.num, (int *)pfns,
pfns, kdata.num, errs,
vma->vm_page_prot,
domid,
vma->vm_private_data);
domid);
if (num < 0)
rc = num;
else if (num != kdata.num) {
unsigned int i;
for (i = 0; i < num; i++) {
rc = pfns[i];
rc = errs[i];
if (rc < 0)
break;
}
......@@ -912,7 +912,7 @@ static void privcmd_close(struct vm_area_struct *vma)
else
pr_crit("unable to unmap MFN range: leaking %d pages. rc=%d\n",
numpgs, rc);
kfree(pages);
kvfree(pages);
}
static vm_fault_t privcmd_fault(struct vm_fault *vmf)
......
......@@ -52,12 +52,12 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order);
#if defined(CONFIG_XEN_PV)
int xen_remap_pfn(struct vm_area_struct *vma, unsigned long addr,
xen_pfn_t *pfn, int nr, int *err_ptr, pgprot_t prot,
unsigned int domid, bool no_translate, struct page **pages);
unsigned int domid, bool no_translate);
#else
static inline int xen_remap_pfn(struct vm_area_struct *vma, unsigned long addr,
xen_pfn_t *pfn, int nr, int *err_ptr,
pgprot_t prot, unsigned int domid,
bool no_translate, struct page **pages)
bool no_translate)
{
BUG();
return 0;
......@@ -134,7 +134,7 @@ static inline int xen_remap_domain_gfn_array(struct vm_area_struct *vma,
*/
BUG_ON(err_ptr == NULL);
return xen_remap_pfn(vma, addr, gfn, nr, err_ptr, prot, domid,
false, pages);
false);
}
/*
......@@ -146,7 +146,6 @@ static inline int xen_remap_domain_gfn_array(struct vm_area_struct *vma,
* @err_ptr: Returns per-MFN error status.
* @prot: page protection mask
* @domid: Domain owning the pages
* @pages: Array of pages if this domain has an auto-translated physmap
*
* @mfn and @err_ptr may point to the same buffer, the MFNs will be
* overwritten by the error codes after they are mapped.
......@@ -157,14 +156,13 @@ static inline int xen_remap_domain_gfn_array(struct vm_area_struct *vma,
static inline int xen_remap_domain_mfn_array(struct vm_area_struct *vma,
unsigned long addr, xen_pfn_t *mfn,
int nr, int *err_ptr,
pgprot_t prot, unsigned int domid,
struct page **pages)
pgprot_t prot, unsigned int domid)
{
if (xen_feature(XENFEAT_auto_translated_physmap))
return -EOPNOTSUPP;
return xen_remap_pfn(vma, addr, mfn, nr, err_ptr, prot, domid,
true, pages);
true);
}
/* xen_remap_domain_gfn_range() - map a range of foreign frames
......@@ -188,8 +186,7 @@ static inline int xen_remap_domain_gfn_range(struct vm_area_struct *vma,
if (xen_feature(XENFEAT_auto_translated_physmap))
return -EOPNOTSUPP;
return xen_remap_pfn(vma, addr, &gfn, nr, NULL, prot, domid, false,
pages);
return xen_remap_pfn(vma, addr, &gfn, nr, NULL, prot, domid, false);
}
int xen_unmap_domain_gfn_range(struct vm_area_struct *vma,
......
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