mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
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:
@@ -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[];
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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", ¤t_state);
|
err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, ...);
|
||||||
|
|||||||
Reference in New Issue
Block a user