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

Pull xen fixes from Juergen Gross:

 - a cleanup of arch/x86/kernel/head_64.S removing the pre-built page
   tables for Xen guests

 - a small comment update

 - another cleanup for Xen PVH guests mode

 - fix an issue with Xen PV-devices backed by driver domains

* tag 'for-linus-7.0-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen/xenbus: better handle backend crash
  xenbus: add xenbus_device parameter to xenbus_read_driver_state()
  x86/PVH: Use boot params to pass RSDP address in start_info page
  x86/xen: update outdated comment
  xen/acpi-processor: fix _CST detection using undersized evaluation buffer
  x86/xen: Build identity mapping page tables dynamically for XENPV
This commit is contained in:
Linus Torvalds
2026-03-07 07:44:32 -08:00
14 changed files with 97 additions and 77 deletions

View File

@@ -19,10 +19,8 @@
extern p4d_t level4_kernel_pgt[512]; extern p4d_t level4_kernel_pgt[512];
extern p4d_t level4_ident_pgt[512]; extern p4d_t level4_ident_pgt[512];
extern pud_t level3_kernel_pgt[512]; extern pud_t level3_kernel_pgt[512];
extern pud_t level3_ident_pgt[512];
extern pmd_t level2_kernel_pgt[512]; extern pmd_t level2_kernel_pgt[512];
extern pmd_t level2_fixmap_pgt[512]; extern pmd_t level2_fixmap_pgt[512];
extern pmd_t level2_ident_pgt[512];
extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM]; extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM];
extern pgd_t init_top_pgt[]; extern pgd_t init_top_pgt[];

View File

@@ -616,38 +616,10 @@ SYM_DATA(early_recursion_flag, .long 0)
.data .data
#if defined(CONFIG_XEN_PV) || defined(CONFIG_PVH)
SYM_DATA_START_PTI_ALIGNED(init_top_pgt)
.quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
.org init_top_pgt + L4_PAGE_OFFSET*8, 0
.quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
.org init_top_pgt + L4_START_KERNEL*8, 0
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
.quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
.fill PTI_USER_PGD_FILL,8,0
SYM_DATA_END(init_top_pgt)
SYM_DATA_START_PAGE_ALIGNED(level3_ident_pgt)
.quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
.fill 511, 8, 0
SYM_DATA_END(level3_ident_pgt)
SYM_DATA_START_PAGE_ALIGNED(level2_ident_pgt)
/*
* Since I easily can, map the first 1G.
* Don't set NX because code runs from these pages.
*
* Note: This sets _PAGE_GLOBAL despite whether
* the CPU supports it or it is enabled. But,
* the CPU should ignore the bit.
*/
PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD)
SYM_DATA_END(level2_ident_pgt)
#else
SYM_DATA_START_PTI_ALIGNED(init_top_pgt) SYM_DATA_START_PTI_ALIGNED(init_top_pgt)
.fill 512,8,0 .fill 512,8,0
.fill PTI_USER_PGD_FILL,8,0 .fill PTI_USER_PGD_FILL,8,0
SYM_DATA_END(init_top_pgt) SYM_DATA_END(init_top_pgt)
#endif
SYM_DATA_START_PAGE_ALIGNED(level4_kernel_pgt) SYM_DATA_START_PAGE_ALIGNED(level4_kernel_pgt)
.fill 511,8,0 .fill 511,8,0

View File

@@ -25,11 +25,6 @@ struct hvm_start_info __initdata pvh_start_info;
const unsigned int __initconst pvh_start_info_sz = sizeof(pvh_start_info); const unsigned int __initconst pvh_start_info_sz = sizeof(pvh_start_info);
static u64 __init pvh_get_root_pointer(void)
{
return pvh_start_info.rsdp_paddr;
}
/* /*
* Xen guests are able to obtain the memory map from the hypervisor via the * Xen guests are able to obtain the memory map from the hypervisor via the
* HYPERVISOR_memory_op hypercall. * HYPERVISOR_memory_op hypercall.
@@ -95,7 +90,7 @@ static void __init init_pvh_bootparams(bool xen_guest)
pvh_bootparams.hdr.version = (2 << 8) | 12; pvh_bootparams.hdr.version = (2 << 8) | 12;
pvh_bootparams.hdr.type_of_loader = ((xen_guest ? 0x9 : 0xb) << 4) | 0; pvh_bootparams.hdr.type_of_loader = ((xen_guest ? 0x9 : 0xb) << 4) | 0;
x86_init.acpi.get_root_pointer = pvh_get_root_pointer; pvh_bootparams.acpi_rsdp_addr = pvh_start_info.rsdp_paddr;
} }
/* /*

View File

@@ -392,7 +392,7 @@ static void __init xen_init_capabilities(void)
/* /*
* Xen PV would need some work to support PCID: CR3 handling as well * Xen PV would need some work to support PCID: CR3 handling as well
* as xen_flush_tlb_others() would need updating. * as xen_flush_tlb_multi() would need updating.
*/ */
setup_clear_cpu_cap(X86_FEATURE_PCID); setup_clear_cpu_cap(X86_FEATURE_PCID);

View File

@@ -105,6 +105,9 @@ pte_t xen_make_pte_init(pteval_t pte);
static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss; static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss;
#endif #endif
static pud_t level3_ident_pgt[PTRS_PER_PUD] __page_aligned_bss;
static pmd_t level2_ident_pgt[PTRS_PER_PMD] __page_aligned_bss;
/* /*
* Protects atomic reservation decrease/increase against concurrent increases. * Protects atomic reservation decrease/increase against concurrent increases.
* Also protects non-atomic updates of current_pages and balloon lists. * Also protects non-atomic updates of current_pages and balloon lists.
@@ -1777,6 +1780,12 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
/* Zap identity mapping */ /* Zap identity mapping */
init_top_pgt[0] = __pgd(0); init_top_pgt[0] = __pgd(0);
init_top_pgt[pgd_index(__PAGE_OFFSET_BASE_L4)].pgd =
__pa_symbol(level3_ident_pgt) + _KERNPG_TABLE_NOENC;
init_top_pgt[pgd_index(__START_KERNEL_map)].pgd =
__pa_symbol(level3_kernel_pgt) + _PAGE_TABLE_NOENC;
level3_ident_pgt[0].pud = __pa_symbol(level2_ident_pgt) + _KERNPG_TABLE_NOENC;
/* Pre-constructed entries are in pfn, so convert to mfn */ /* Pre-constructed entries are in pfn, so convert to mfn */
/* L4[273] -> level3_ident_pgt */ /* L4[273] -> level3_ident_pgt */
/* L4[511] -> level3_kernel_pgt */ /* L4[511] -> level3_kernel_pgt */

View File

@@ -1646,7 +1646,7 @@ static int xennet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
/* avoid the race with XDP headroom adjustment */ /* avoid the race with XDP headroom adjustment */
wait_event(module_wq, wait_event(module_wq,
xenbus_read_driver_state(np->xbdev->otherend) == xenbus_read_driver_state(np->xbdev, np->xbdev->otherend) ==
XenbusStateReconfigured); XenbusStateReconfigured);
np->netfront_xdp_enabled = true; np->netfront_xdp_enabled = true;
@@ -1764,9 +1764,9 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
do { do {
xenbus_switch_state(dev, XenbusStateInitialising); xenbus_switch_state(dev, XenbusStateInitialising);
err = wait_event_timeout(module_wq, err = wait_event_timeout(module_wq,
xenbus_read_driver_state(dev->otherend) != xenbus_read_driver_state(dev, dev->otherend) !=
XenbusStateClosed && XenbusStateClosed &&
xenbus_read_driver_state(dev->otherend) != xenbus_read_driver_state(dev, dev->otherend) !=
XenbusStateUnknown, XENNET_TIMEOUT); XenbusStateUnknown, XENNET_TIMEOUT);
} while (!err); } while (!err);
@@ -2626,31 +2626,31 @@ static void xennet_bus_close(struct xenbus_device *dev)
{ {
int ret; int ret;
if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
return; return;
do { do {
xenbus_switch_state(dev, XenbusStateClosing); xenbus_switch_state(dev, XenbusStateClosing);
ret = wait_event_timeout(module_wq, ret = wait_event_timeout(module_wq,
xenbus_read_driver_state(dev->otherend) == xenbus_read_driver_state(dev, dev->otherend) ==
XenbusStateClosing || XenbusStateClosing ||
xenbus_read_driver_state(dev->otherend) == xenbus_read_driver_state(dev, dev->otherend) ==
XenbusStateClosed || XenbusStateClosed ||
xenbus_read_driver_state(dev->otherend) == xenbus_read_driver_state(dev, dev->otherend) ==
XenbusStateUnknown, XenbusStateUnknown,
XENNET_TIMEOUT); XENNET_TIMEOUT);
} while (!ret); } while (!ret);
if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
return; return;
do { do {
xenbus_switch_state(dev, XenbusStateClosed); xenbus_switch_state(dev, XenbusStateClosed);
ret = wait_event_timeout(module_wq, ret = wait_event_timeout(module_wq,
xenbus_read_driver_state(dev->otherend) == xenbus_read_driver_state(dev, dev->otherend) ==
XenbusStateClosed || XenbusStateClosed ||
xenbus_read_driver_state(dev->otherend) == xenbus_read_driver_state(dev, dev->otherend) ==
XenbusStateUnknown, XenbusStateUnknown,
XENNET_TIMEOUT); XENNET_TIMEOUT);
} while (!ret); } while (!ret);
} }

View File

@@ -856,7 +856,7 @@ static void pcifront_try_connect(struct pcifront_device *pdev)
int err; int err;
/* Only connect once */ /* Only connect once */
if (xenbus_read_driver_state(pdev->xdev->nodename) != if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
XenbusStateInitialised) XenbusStateInitialised)
return; return;
@@ -876,7 +876,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
enum xenbus_state prev_state; enum xenbus_state prev_state;
prev_state = xenbus_read_driver_state(pdev->xdev->nodename); prev_state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
if (prev_state >= XenbusStateClosing) if (prev_state >= XenbusStateClosing)
goto out; goto out;
@@ -895,7 +895,7 @@ out:
static void pcifront_attach_devices(struct pcifront_device *pdev) static void pcifront_attach_devices(struct pcifront_device *pdev)
{ {
if (xenbus_read_driver_state(pdev->xdev->nodename) == if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) ==
XenbusStateReconfiguring) XenbusStateReconfiguring)
pcifront_connect(pdev); pcifront_connect(pdev);
} }
@@ -909,7 +909,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
char str[64]; char str[64];
state = xenbus_read_driver_state(pdev->xdev->nodename); state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
if (state == XenbusStateInitialised) { if (state == XenbusStateInitialised) {
dev_dbg(&pdev->xdev->dev, "Handle skipped connect.\n"); dev_dbg(&pdev->xdev->dev, "Handle skipped connect.\n");
/* We missed Connected and need to initialize. */ /* We missed Connected and need to initialize. */

View File

@@ -1175,7 +1175,7 @@ static void scsifront_backend_changed(struct xenbus_device *dev,
return; return;
} }
if (xenbus_read_driver_state(dev->nodename) == if (xenbus_read_driver_state(dev, dev->nodename) ==
XenbusStateInitialised) XenbusStateInitialised)
scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN); scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);

View File

@@ -378,11 +378,8 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
acpi_psd[acpi_id].domain); acpi_psd[acpi_id].domain);
} }
status = acpi_evaluate_object(handle, "_CST", NULL, &buffer); if (!pblk && !acpi_has_method(handle, "_CST"))
if (ACPI_FAILURE(status)) { return AE_OK;
if (!pblk)
return AE_OK;
}
/* .. and it has a C-state */ /* .. and it has a C-state */
__set_bit(acpi_id, acpi_id_cst_present); __set_bit(acpi_id, acpi_id_cst_present);

View File

@@ -149,12 +149,12 @@ static int xen_pcibk_attach(struct xen_pcibk_device *pdev)
mutex_lock(&pdev->dev_lock); mutex_lock(&pdev->dev_lock);
/* Make sure we only do this setup once */ /* Make sure we only do this setup once */
if (xenbus_read_driver_state(pdev->xdev->nodename) != if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
XenbusStateInitialised) XenbusStateInitialised)
goto out; goto out;
/* Wait for frontend to state that it has published the configuration */ /* Wait for frontend to state that it has published the configuration */
if (xenbus_read_driver_state(pdev->xdev->otherend) != if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->otherend) !=
XenbusStateInitialised) XenbusStateInitialised)
goto out; goto out;
@@ -374,7 +374,7 @@ static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev,
dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n"); dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
mutex_lock(&pdev->dev_lock); mutex_lock(&pdev->dev_lock);
if (xenbus_read_driver_state(pdev->xdev->nodename) != state) if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) != state)
goto out; goto out;
err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d", err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
@@ -572,7 +572,7 @@ static int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev)
/* It's possible we could get the call to setup twice, so make sure /* It's possible we could get the call to setup twice, so make sure
* we're not already connected. * we're not already connected.
*/ */
if (xenbus_read_driver_state(pdev->xdev->nodename) != if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
XenbusStateInitWait) XenbusStateInitWait)
goto out; goto out;
@@ -662,7 +662,7 @@ static void xen_pcibk_be_watch(struct xenbus_watch *watch,
struct xen_pcibk_device *pdev = struct xen_pcibk_device *pdev =
container_of(watch, struct xen_pcibk_device, be_watch); container_of(watch, struct xen_pcibk_device, be_watch);
switch (xenbus_read_driver_state(pdev->xdev->nodename)) { switch (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename)) {
case XenbusStateInitWait: case XenbusStateInitWait:
xen_pcibk_setup_backend(pdev); xen_pcibk_setup_backend(pdev);
break; break;

View File

@@ -226,8 +226,9 @@ __xenbus_switch_state(struct xenbus_device *dev,
struct xenbus_transaction xbt; struct xenbus_transaction xbt;
int current_state; int current_state;
int err, abort; int err, abort;
bool vanished = false;
if (state == dev->state) if (state == dev->state || dev->vanished)
return 0; return 0;
again: again:
@@ -242,6 +243,10 @@ again:
err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state); err = xenbus_scanf(xbt, dev->nodename, "state", "%d", &current_state);
if (err != 1) if (err != 1)
goto abort; goto abort;
if (current_state != dev->state && current_state == XenbusStateInitialising) {
vanished = true;
goto abort;
}
err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
if (err) { if (err) {
@@ -256,7 +261,7 @@ abort:
if (err == -EAGAIN && !abort) if (err == -EAGAIN && !abort)
goto again; goto again;
xenbus_switch_fatal(dev, depth, err, "ending transaction"); xenbus_switch_fatal(dev, depth, err, "ending transaction");
} else } else if (!vanished)
dev->state = state; dev->state = state;
return 0; return 0;
@@ -931,14 +936,20 @@ static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr)
/** /**
* xenbus_read_driver_state - read state from a store path * xenbus_read_driver_state - read state from a store path
* @dev: xenbus device pointer
* @path: path for driver * @path: path for driver
* *
* Returns: the state of the driver rooted at the given store path, or * Returns: the state of the driver rooted at the given store path, or
* XenbusStateUnknown if no state can be read. * XenbusStateUnknown if no state can be read.
*/ */
enum xenbus_state xenbus_read_driver_state(const char *path) enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
const char *path)
{ {
enum xenbus_state result; enum xenbus_state result;
if (dev && dev->vanished)
return XenbusStateUnknown;
int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL); int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
if (err) if (err)
result = XenbusStateUnknown; result = XenbusStateUnknown;

View File

@@ -191,7 +191,7 @@ void xenbus_otherend_changed(struct xenbus_watch *watch,
return; return;
} }
state = xenbus_read_driver_state(dev->otherend); state = xenbus_read_driver_state(dev, dev->otherend);
dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n", dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
state, xenbus_strstate(state), dev->otherend_watch.node, path); state, xenbus_strstate(state), dev->otherend_watch.node, path);
@@ -364,7 +364,7 @@ void xenbus_dev_remove(struct device *_dev)
* closed. * closed.
*/ */
if (!drv->allow_rebind || if (!drv->allow_rebind ||
xenbus_read_driver_state(dev->nodename) == XenbusStateClosing) xenbus_read_driver_state(dev, dev->nodename) == XenbusStateClosing)
xenbus_switch_state(dev, XenbusStateClosed); xenbus_switch_state(dev, XenbusStateClosed);
} }
EXPORT_SYMBOL_GPL(xenbus_dev_remove); EXPORT_SYMBOL_GPL(xenbus_dev_remove);
@@ -444,6 +444,9 @@ static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
info.dev = NULL; info.dev = NULL;
bus_for_each_dev(bus, NULL, &info, cleanup_dev); bus_for_each_dev(bus, NULL, &info, cleanup_dev);
if (info.dev) { if (info.dev) {
dev_warn(&info.dev->dev,
"device forcefully removed from xenstore\n");
info.dev->vanished = true;
device_unregister(&info.dev->dev); device_unregister(&info.dev->dev);
put_device(&info.dev->dev); put_device(&info.dev->dev);
} }
@@ -514,7 +517,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
size_t stringlen; size_t stringlen;
char *tmpstring; char *tmpstring;
enum xenbus_state state = xenbus_read_driver_state(nodename); enum xenbus_state state = xenbus_read_driver_state(NULL, nodename);
if (state != XenbusStateInitialising) { if (state != XenbusStateInitialising) {
/* Device is not new, so ignore it. This can happen if a /* Device is not new, so ignore it. This can happen if a
@@ -659,6 +662,39 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
return; return;
dev = xenbus_device_find(root, &bus->bus); dev = xenbus_device_find(root, &bus->bus);
/*
* Backend domain crash results in not coordinated frontend removal,
* without going through XenbusStateClosing. If this is a new instance
* of the same device Xen tools will have reset the state to
* XenbusStateInitializing.
* It might be that the backend crashed early during the init phase of
* device setup, in which case the known state would have been
* XenbusStateInitializing. So test the backend domid to match the
* saved one. In case the new backend happens to have the same domid as
* the old one, we can just carry on, as there is no inconsistency
* resulting in this case.
*/
if (dev && !strcmp(bus->root, "device")) {
enum xenbus_state state = xenbus_read_driver_state(dev, dev->nodename);
unsigned int backend = xenbus_read_unsigned(root, "backend-id",
dev->otherend_id);
if (state == XenbusStateInitialising &&
(state != dev->state || backend != dev->otherend_id)) {
/*
* State has been reset, assume the old one vanished
* and new one needs to be probed.
*/
dev_warn(&dev->dev,
"state reset occurred, reconnecting\n");
dev->vanished = true;
}
if (dev->vanished) {
device_unregister(&dev->dev);
put_device(&dev->dev);
dev = NULL;
}
}
if (!dev) if (!dev)
xenbus_probe_node(bus, type, root); xenbus_probe_node(bus, type, root);
else else

View File

@@ -253,7 +253,7 @@ static int print_device_status(struct device *dev, void *data)
} else if (xendev->state < XenbusStateConnected) { } else if (xendev->state < XenbusStateConnected) {
enum xenbus_state rstate = XenbusStateUnknown; enum xenbus_state rstate = XenbusStateUnknown;
if (xendev->otherend) if (xendev->otherend)
rstate = xenbus_read_driver_state(xendev->otherend); rstate = xenbus_read_driver_state(xendev, xendev->otherend);
pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n", pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n",
xendev->nodename, xendev->state, rstate); xendev->nodename, xendev->state, rstate);
} }

View File

@@ -80,6 +80,7 @@ struct xenbus_device {
const char *devicetype; const char *devicetype;
const char *nodename; const char *nodename;
const char *otherend; const char *otherend;
bool vanished;
int otherend_id; int otherend_id;
struct xenbus_watch otherend_watch; struct xenbus_watch otherend_watch;
struct device dev; struct device dev;
@@ -228,7 +229,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr);
int xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port); int xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port);
int xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port); int xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port);
enum xenbus_state xenbus_read_driver_state(const char *path); enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
const char *path);
__printf(3, 4) __printf(3, 4)
void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...); void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);