Commit 81ae31d7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'stable/for-linus-3.18-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip

Pull Xen updates from David Vrabel:
 "Features and fixes:

   - Add pvscsi frontend and backend drivers.
   - Remove _PAGE_IOMAP PTE flag, freeing it for alternate uses.
   - Try and keep memory contiguous during PV memory setup (reduces
     SWIOTLB usage).
   - Allow front/back drivers to use threaded irqs.
   - Support large initrds in PV guests.
   - Fix PVH guests in preparation for Xen 4.5"

* tag 'stable/for-linus-3.18-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip: (22 commits)
  xen: remove DEFINE_XENBUS_DRIVER() macro
  xen/xenbus: Remove BUG_ON() when error string trucated
  xen/xenbus: Correct the comments for xenbus_grant_ring()
  x86/xen: Set EFER.NX and EFER.SCE in PVH guests
  xen: eliminate scalability issues from initrd handling
  xen: sync some headers with xen tree
  xen: make pvscsi frontend dependant on xenbus frontend
  arm{,64}/xen: Remove "EXPERIMENTAL" in the description of the Xen options
  xen-scsifront: don't deadlock if the ring becomes full
  x86: remove the Xen-specific _PAGE_IOMAP PTE flag
  x86/xen: do not use _PAGE_IOMAP PTE flag for I/O mappings
  x86: skip check for spurious faults for non-present faults
  xen/efi: Directly include needed headers
  xen-scsiback: clean up a type issue in scsiback_make_tpg()
  xen-scsifront: use GFP_ATOMIC under spin_lock
  MAINTAINERS: Add xen pvscsi maintainer
  xen-scsiback: Add Xen PV SCSI backend driver
  xen-scsifront: Add Xen PV SCSI frontend driver
  xen: Add Xen pvSCSI protocol description
  xen/events: support threaded irqs for interdomain event channels
  ...
parents ef4a48c5 95afae48
...@@ -10268,6 +10268,15 @@ S: Supported ...@@ -10268,6 +10268,15 @@ S: Supported
F: drivers/block/xen-blkback/* F: drivers/block/xen-blkback/*
F: drivers/block/xen* F: drivers/block/xen*
XEN PVSCSI DRIVERS
M: Juergen Gross <jgross@suse.com>
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/xen-scsifront.c
F: drivers/xen/xen-scsiback.c
F: include/xen/interface/io/vscsiif.h
XEN SWIOTLB SUBSYSTEM XEN SWIOTLB SUBSYSTEM
M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
L: xen-devel@lists.xenproject.org (moderated for non-subscribers) L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
......
...@@ -1779,7 +1779,7 @@ config XEN_DOM0 ...@@ -1779,7 +1779,7 @@ config XEN_DOM0
depends on XEN depends on XEN
config XEN config XEN
bool "Xen guest support on ARM (EXPERIMENTAL)" bool "Xen guest support on ARM"
depends on ARM && AEABI && OF depends on ARM && AEABI && OF
depends on CPU_V7 && !CPU_V6 depends on CPU_V7 && !CPU_V6
depends on !GENERIC_ATOMIC64 depends on !GENERIC_ATOMIC64
......
...@@ -349,7 +349,7 @@ config XEN_DOM0 ...@@ -349,7 +349,7 @@ config XEN_DOM0
depends on XEN depends on XEN
config XEN config XEN
bool "Xen guest support on ARM64 (EXPERIMENTAL)" bool "Xen guest support on ARM64"
depends on ARM64 && OF depends on ARM64 && OF
select SWIOTLB_XEN select SWIOTLB_XEN
help help
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#define _PAGE_BIT_SPECIAL _PAGE_BIT_SOFTW1 #define _PAGE_BIT_SPECIAL _PAGE_BIT_SOFTW1
#define _PAGE_BIT_CPA_TEST _PAGE_BIT_SOFTW1 #define _PAGE_BIT_CPA_TEST _PAGE_BIT_SOFTW1
#define _PAGE_BIT_SPLITTING _PAGE_BIT_SOFTW2 /* only valid on a PSE pmd */ #define _PAGE_BIT_SPLITTING _PAGE_BIT_SOFTW2 /* only valid on a PSE pmd */
#define _PAGE_BIT_IOMAP _PAGE_BIT_SOFTW2 /* flag used to indicate IO mapping */
#define _PAGE_BIT_HIDDEN _PAGE_BIT_SOFTW3 /* hidden by kmemcheck */ #define _PAGE_BIT_HIDDEN _PAGE_BIT_SOFTW3 /* hidden by kmemcheck */
#define _PAGE_BIT_SOFT_DIRTY _PAGE_BIT_SOFTW3 /* software dirty tracking */ #define _PAGE_BIT_SOFT_DIRTY _PAGE_BIT_SOFTW3 /* software dirty tracking */
#define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */ #define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */
...@@ -52,7 +51,7 @@ ...@@ -52,7 +51,7 @@
#define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE) #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE)
#define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL)
#define _PAGE_SOFTW1 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW1) #define _PAGE_SOFTW1 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW1)
#define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP) #define _PAGE_SOFTW2 (_AT(pteval_t, 1) << _PAGE_BIT_SOFTW2)
#define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT)
#define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE) #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE)
#define _PAGE_SPECIAL (_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL) #define _PAGE_SPECIAL (_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL)
...@@ -168,10 +167,10 @@ ...@@ -168,10 +167,10 @@
#define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE) #define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE)
#define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE) #define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE)
#define __PAGE_KERNEL_IO (__PAGE_KERNEL | _PAGE_IOMAP) #define __PAGE_KERNEL_IO (__PAGE_KERNEL)
#define __PAGE_KERNEL_IO_NOCACHE (__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP) #define __PAGE_KERNEL_IO_NOCACHE (__PAGE_KERNEL_NOCACHE)
#define __PAGE_KERNEL_IO_UC_MINUS (__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP) #define __PAGE_KERNEL_IO_UC_MINUS (__PAGE_KERNEL_UC_MINUS)
#define __PAGE_KERNEL_IO_WC (__PAGE_KERNEL_WC | _PAGE_IOMAP) #define __PAGE_KERNEL_IO_WC (__PAGE_KERNEL_WC)
#define PAGE_KERNEL __pgprot(__PAGE_KERNEL) #define PAGE_KERNEL __pgprot(__PAGE_KERNEL)
#define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO) #define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO)
......
...@@ -933,8 +933,17 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte) ...@@ -933,8 +933,17 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte)
* cross-processor TLB flush, even if no stale TLB entries exist * cross-processor TLB flush, even if no stale TLB entries exist
* on other processors. * on other processors.
* *
* Spurious faults may only occur if the TLB contains an entry with
* fewer permission than the page table entry. Non-present (P = 0)
* and reserved bit (R = 1) faults are never spurious.
*
* There are no security implications to leaving a stale TLB when * There are no security implications to leaving a stale TLB when
* increasing the permissions on a page. * increasing the permissions on a page.
*
* Returns non-zero if a spurious fault was handled, zero otherwise.
*
* See Intel Developer's Manual Vol 3 Section 4.10.4.3, bullet 3
* (Optional Invalidation).
*/ */
static noinline int static noinline int
spurious_fault(unsigned long error_code, unsigned long address) spurious_fault(unsigned long error_code, unsigned long address)
...@@ -945,8 +954,17 @@ spurious_fault(unsigned long error_code, unsigned long address) ...@@ -945,8 +954,17 @@ spurious_fault(unsigned long error_code, unsigned long address)
pte_t *pte; pte_t *pte;
int ret; int ret;
/* Reserved-bit violation or user access to kernel space? */ /*
if (error_code & (PF_USER | PF_RSVD)) * Only writes to RO or instruction fetches from NX may cause
* spurious faults.
*
* These could be from user or supervisor accesses but the TLB
* is only lazily flushed after a kernel mapping protection
* change, so user accesses are not expected to cause spurious
* faults.
*/
if (error_code != (PF_WRITE | PF_PROT)
&& error_code != (PF_INSTR | PF_PROT))
return 0; return 0;
pgd = init_mm.pgd + pgd_index(address); pgd = init_mm.pgd + pgd_index(address);
......
...@@ -537,7 +537,7 @@ static void __init pagetable_init(void) ...@@ -537,7 +537,7 @@ static void __init pagetable_init(void)
permanent_kmaps_init(pgd_base); permanent_kmaps_init(pgd_base);
} }
pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP); pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL);
EXPORT_SYMBOL_GPL(__supported_pte_mask); EXPORT_SYMBOL_GPL(__supported_pte_mask);
/* user-defined highmem size */ /* user-defined highmem size */
......
...@@ -151,7 +151,7 @@ early_param("gbpages", parse_direct_gbpages_on); ...@@ -151,7 +151,7 @@ early_param("gbpages", parse_direct_gbpages_on);
* around without checking the pgd every time. * around without checking the pgd every time.
*/ */
pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP; pteval_t __supported_pte_mask __read_mostly = ~0;
EXPORT_SYMBOL_GPL(__supported_pte_mask); EXPORT_SYMBOL_GPL(__supported_pte_mask);
int force_personality32; int force_personality32;
......
...@@ -442,8 +442,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, ...@@ -442,8 +442,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
*/ */
prot |= _PAGE_CACHE_UC_MINUS; prot |= _PAGE_CACHE_UC_MINUS;
prot |= _PAGE_IOMAP; /* creating a mapping for IO */
vma->vm_page_prot = __pgprot(prot); vma->vm_page_prot = __pgprot(prot);
if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
......
...@@ -15,12 +15,14 @@ ...@@ -15,12 +15,14 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/bitops.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/string.h> #include <linux/string.h>
#include <xen/xen-ops.h> #include <xen/xen-ops.h>
#include <asm/page.h>
#include <asm/setup.h> #include <asm/setup.h>
void __init xen_efi_init(void) void __init xen_efi_init(void)
......
...@@ -1463,6 +1463,7 @@ static void __ref xen_setup_gdt(int cpu) ...@@ -1463,6 +1463,7 @@ static void __ref xen_setup_gdt(int cpu)
pv_cpu_ops.load_gdt = xen_load_gdt; pv_cpu_ops.load_gdt = xen_load_gdt;
} }
#ifdef CONFIG_XEN_PVH
/* /*
* A PV guest starts with default flags that are not set for PVH, set them * A PV guest starts with default flags that are not set for PVH, set them
* here asap. * here asap.
...@@ -1508,17 +1509,21 @@ static void __init xen_pvh_early_guest_init(void) ...@@ -1508,17 +1509,21 @@ static void __init xen_pvh_early_guest_init(void)
return; return;
xen_have_vector_callback = 1; xen_have_vector_callback = 1;
xen_pvh_early_cpu_init(0, false);
xen_pvh_set_cr_flags(0); xen_pvh_set_cr_flags(0);
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
BUG(); /* PVH: Implement proper support. */ BUG(); /* PVH: Implement proper support. */
#endif #endif
} }
#endif /* CONFIG_XEN_PVH */
/* First C function to be called on Xen boot */ /* First C function to be called on Xen boot */
asmlinkage __visible void __init xen_start_kernel(void) asmlinkage __visible void __init xen_start_kernel(void)
{ {
struct physdev_set_iopl set_iopl; struct physdev_set_iopl set_iopl;
unsigned long initrd_start = 0;
int rc; int rc;
if (!xen_start_info) if (!xen_start_info)
...@@ -1527,7 +1532,9 @@ asmlinkage __visible void __init xen_start_kernel(void) ...@@ -1527,7 +1532,9 @@ asmlinkage __visible void __init xen_start_kernel(void)
xen_domain_type = XEN_PV_DOMAIN; xen_domain_type = XEN_PV_DOMAIN;
xen_setup_features(); xen_setup_features();
#ifdef CONFIG_XEN_PVH
xen_pvh_early_guest_init(); xen_pvh_early_guest_init();
#endif
xen_setup_machphys_mapping(); xen_setup_machphys_mapping();
/* Install Xen paravirt ops */ /* Install Xen paravirt ops */
...@@ -1559,8 +1566,6 @@ asmlinkage __visible void __init xen_start_kernel(void) ...@@ -1559,8 +1566,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
#endif #endif
__supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD);
__supported_pte_mask |= _PAGE_IOMAP;
/* /*
* Prevent page tables from being allocated in highmem, even * Prevent page tables from being allocated in highmem, even
* if CONFIG_HIGHPTE is enabled. * if CONFIG_HIGHPTE is enabled.
...@@ -1667,10 +1672,16 @@ asmlinkage __visible void __init xen_start_kernel(void) ...@@ -1667,10 +1672,16 @@ asmlinkage __visible void __init xen_start_kernel(void)
new_cpu_data.x86_capability[0] = cpuid_edx(1); new_cpu_data.x86_capability[0] = cpuid_edx(1);
#endif #endif
if (xen_start_info->mod_start) {
if (xen_start_info->flags & SIF_MOD_START_PFN)
initrd_start = PFN_PHYS(xen_start_info->mod_start);
else
initrd_start = __pa(xen_start_info->mod_start);
}
/* Poke various useful things into boot_params */ /* Poke various useful things into boot_params */
boot_params.hdr.type_of_loader = (9 << 4) | 0; boot_params.hdr.type_of_loader = (9 << 4) | 0;
boot_params.hdr.ramdisk_image = xen_start_info->mod_start boot_params.hdr.ramdisk_image = initrd_start;
? __pa(xen_start_info->mod_start) : 0;
boot_params.hdr.ramdisk_size = xen_start_info->mod_len; boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line); boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line);
......
...@@ -399,38 +399,14 @@ static pteval_t pte_pfn_to_mfn(pteval_t val) ...@@ -399,38 +399,14 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
if (unlikely(mfn == INVALID_P2M_ENTRY)) { if (unlikely(mfn == INVALID_P2M_ENTRY)) {
mfn = 0; mfn = 0;
flags = 0; flags = 0;
} else { } else
/* mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT);
* Paramount to do this test _after_ the
* INVALID_P2M_ENTRY as INVALID_P2M_ENTRY &
* IDENTITY_FRAME_BIT resolves to true.
*/
mfn &= ~FOREIGN_FRAME_BIT;
if (mfn & IDENTITY_FRAME_BIT) {
mfn &= ~IDENTITY_FRAME_BIT;
flags |= _PAGE_IOMAP;
}
}
val = ((pteval_t)mfn << PAGE_SHIFT) | flags; val = ((pteval_t)mfn << PAGE_SHIFT) | flags;
} }
return val; return val;
} }
static pteval_t iomap_pte(pteval_t val)
{
if (val & _PAGE_PRESENT) {
unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
pteval_t flags = val & PTE_FLAGS_MASK;
/* We assume the pte frame number is a MFN, so
just use it as-is. */
val = ((pteval_t)pfn << PAGE_SHIFT) | flags;
}
return val;
}
__visible pteval_t xen_pte_val(pte_t pte) __visible pteval_t xen_pte_val(pte_t pte)
{ {
pteval_t pteval = pte.pte; pteval_t pteval = pte.pte;
...@@ -441,9 +417,6 @@ __visible pteval_t xen_pte_val(pte_t pte) ...@@ -441,9 +417,6 @@ __visible pteval_t xen_pte_val(pte_t pte)
pteval = (pteval & ~_PAGE_PAT) | _PAGE_PWT; pteval = (pteval & ~_PAGE_PAT) | _PAGE_PWT;
} }
#endif #endif
if (xen_initial_domain() && (pteval & _PAGE_IOMAP))
return pteval;
return pte_mfn_to_pfn(pteval); return pte_mfn_to_pfn(pteval);
} }
PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val); PV_CALLEE_SAVE_REGS_THUNK(xen_pte_val);
...@@ -481,7 +454,6 @@ void xen_set_pat(u64 pat) ...@@ -481,7 +454,6 @@ void xen_set_pat(u64 pat)
__visible pte_t xen_make_pte(pteval_t pte) __visible pte_t xen_make_pte(pteval_t pte)
{ {
phys_addr_t addr = (pte & PTE_PFN_MASK);
#if 0 #if 0
/* If Linux is trying to set a WC pte, then map to the Xen WC. /* If Linux is trying to set a WC pte, then map to the Xen WC.
* If _PAGE_PAT is set, then it probably means it is really * If _PAGE_PAT is set, then it probably means it is really
...@@ -496,19 +468,7 @@ __visible pte_t xen_make_pte(pteval_t pte) ...@@ -496,19 +468,7 @@ __visible pte_t xen_make_pte(pteval_t pte)
pte = (pte & ~(_PAGE_PCD | _PAGE_PWT)) | _PAGE_PAT; pte = (pte & ~(_PAGE_PCD | _PAGE_PWT)) | _PAGE_PAT;
} }
#endif #endif
/* pte = pte_pfn_to_mfn(pte);
* Unprivileged domains are allowed to do IOMAPpings for
* PCI passthrough, but not map ISA space. The ISA
* mappings are just dummy local mappings to keep other
* parts of the kernel happy.
*/
if (unlikely(pte & _PAGE_IOMAP) &&
(xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
pte = iomap_pte(pte);
} else {
pte &= ~_PAGE_IOMAP;
pte = pte_pfn_to_mfn(pte);
}
return native_make_pte(pte); return native_make_pte(pte);
} }
...@@ -2091,7 +2051,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) ...@@ -2091,7 +2051,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
default: default:
/* By default, set_fixmap is used for hardware mappings */ /* By default, set_fixmap is used for hardware mappings */
pte = mfn_pte(phys, __pgprot(pgprot_val(prot) | _PAGE_IOMAP)); pte = mfn_pte(phys, prot);
break; break;
} }
......
...@@ -173,6 +173,7 @@ ...@@ -173,6 +173,7 @@
#include <xen/balloon.h> #include <xen/balloon.h>
#include <xen/grant_table.h> #include <xen/grant_table.h>
#include "p2m.h"
#include "multicalls.h" #include "multicalls.h"
#include "xen-ops.h" #include "xen-ops.h"
...@@ -180,12 +181,6 @@ static void __init m2p_override_init(void); ...@@ -180,12 +181,6 @@ static void __init m2p_override_init(void);
unsigned long xen_max_p2m_pfn __read_mostly; unsigned long xen_max_p2m_pfn __read_mostly;
#define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
#define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *))
#define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **))
#define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
/* Placeholders for holes in the address space */ /* Placeholders for holes in the address space */
static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE); static RESERVE_BRK_ARRAY(unsigned long, p2m_missing, P2M_PER_PAGE);
static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE); static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_missing, P2M_MID_PER_PAGE);
...@@ -202,16 +197,12 @@ static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE); ...@@ -202,16 +197,12 @@ static RESERVE_BRK_ARRAY(unsigned long, p2m_mid_identity_mfn, P2M_MID_PER_PAGE);
RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE))); RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
/* We might hit two boundary violations at the start and end, at max each /* For each I/O range remapped we may lose up to two leaf pages for the boundary
* boundary violation will require three middle nodes. */ * violations and three mid pages to cover up to 3GB. With
RESERVE_BRK(p2m_mid_extra, PAGE_SIZE * 2 * 3); * early_can_reuse_p2m_middle() most of the leaf pages will be reused by the
* remapped region.
/* When we populate back during bootup, the amount of pages can vary. The */
* max we have is seen is 395979, but that does not mean it can't be more. RESERVE_BRK(p2m_identity_remap, PAGE_SIZE * 2 * 3 * MAX_REMAP_RANGES);
* Some machines can have 3GB I/O holes even. With early_can_reuse_p2m_middle
* it can re-use Xen provided mfn_list array, so we only need to allocate at
* most three P2M top nodes. */
RESERVE_BRK(p2m_populated, PAGE_SIZE * 3);
static inline unsigned p2m_top_index(unsigned long pfn) static inline unsigned p2m_top_index(unsigned long pfn)
{ {
......
#ifndef _XEN_P2M_H
#define _XEN_P2M_H
#define P2M_PER_PAGE (PAGE_SIZE / sizeof(unsigned long))
#define P2M_MID_PER_PAGE (PAGE_SIZE / sizeof(unsigned long *))
#define P2M_TOP_PER_PAGE (PAGE_SIZE / sizeof(unsigned long **))
#define MAX_P2M_PFN (P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE)
#define MAX_REMAP_RANGES 10
extern unsigned long __init set_phys_range_identity(unsigned long pfn_s,
unsigned long pfn_e);
#endif /* _XEN_P2M_H */
This diff is collapsed.
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <xen/hvc-console.h> #include <xen/hvc-console.h>
#include "xen-ops.h" #include "xen-ops.h"
#include "mmu.h" #include "mmu.h"
#include "smp.h"
cpumask_var_t xen_cpu_initialized_map; cpumask_var_t xen_cpu_initialized_map;
...@@ -99,10 +100,14 @@ static void cpu_bringup(void) ...@@ -99,10 +100,14 @@ static void cpu_bringup(void)
wmb(); /* make sure everything is out */ wmb(); /* make sure everything is out */
} }
/* Note: cpu parameter is only relevant for PVH */ /*
static void cpu_bringup_and_idle(int cpu) * Note: cpu parameter is only relevant for PVH. The reason for passing it
* is we can't do smp_processor_id until the percpu segments are loaded, for
* which we need the cpu number! So we pass it in rdi as first parameter.
*/
asmlinkage __visible void cpu_bringup_and_idle(int cpu)
{ {
#ifdef CONFIG_X86_64 #ifdef CONFIG_XEN_PVH
if (xen_feature(XENFEAT_auto_translated_physmap) && if (xen_feature(XENFEAT_auto_translated_physmap) &&
xen_feature(XENFEAT_supervisor_mode_kernel)) xen_feature(XENFEAT_supervisor_mode_kernel))
xen_pvh_secondary_vcpu_init(cpu); xen_pvh_secondary_vcpu_init(cpu);
...@@ -374,11 +379,10 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) ...@@ -374,11 +379,10 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
ctxt->user_regs.fs = __KERNEL_PERCPU; ctxt->user_regs.fs = __KERNEL_PERCPU;
ctxt->user_regs.gs = __KERNEL_STACK_CANARY; ctxt->user_regs.gs = __KERNEL_STACK_CANARY;
#endif #endif
ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt)); memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
if (!xen_feature(XENFEAT_auto_translated_physmap)) { if (!xen_feature(XENFEAT_auto_translated_physmap)) {
ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
ctxt->flags = VGCF_IN_KERNEL; ctxt->flags = VGCF_IN_KERNEL;
ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */ ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
ctxt->user_regs.ds = __USER_DS; ctxt->user_regs.ds = __USER_DS;
...@@ -413,15 +417,18 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) ...@@ -413,15 +417,18 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
(unsigned long)xen_failsafe_callback; (unsigned long)xen_failsafe_callback;
ctxt->user_regs.cs = __KERNEL_CS; ctxt->user_regs.cs = __KERNEL_CS;
per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir); per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
#ifdef CONFIG_X86_32
} }
#else #ifdef CONFIG_XEN_PVH
} else else {
/* N.B. The user_regs.eip (cpu_bringup_and_idle) is called with /*
* %rdi having the cpu number - which means are passing in * The vcpu comes on kernel page tables which have the NX pte
* as the first parameter the cpu. Subtle! * bit set. This means before DS/SS is touched, NX in
* EFER must be set. Hence the following assembly glue code.
*/ */
ctxt->user_regs.eip = (unsigned long)xen_pvh_early_cpu_init;
ctxt->user_regs.rdi = cpu; ctxt->user_regs.rdi = cpu;
ctxt->user_regs.rsi = true; /* entry == true */
}
#endif #endif
ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs); ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir)); ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
......
...@@ -8,4 +8,12 @@ extern void xen_send_IPI_allbutself(int vector); ...@@ -8,4 +8,12 @@ extern void xen_send_IPI_allbutself(int vector);
extern void xen_send_IPI_all(int vector); extern void xen_send_IPI_all(int vector);
extern void xen_send_IPI_self(int vector); extern void xen_send_IPI_self(int vector);
#ifdef CONFIG_XEN_PVH
extern void xen_pvh_early_cpu_init(int cpu, bool entry);
#else
static inline void xen_pvh_early_cpu_init(int cpu, bool entry)
{
}
#endif
#endif #endif
...@@ -47,6 +47,41 @@ ENTRY(startup_xen) ...@@ -47,6 +47,41 @@ ENTRY(startup_xen)
__FINIT __FINIT
#ifdef CONFIG_XEN_PVH
/*
* xen_pvh_early_cpu_init() - early PVH VCPU initialization
* @cpu: this cpu number (%rdi)
* @entry: true if this is a secondary vcpu coming up on this entry
* point, false if this is the boot CPU being initialized for
* the first time (%rsi)
*
* Note: This is called as a function on the boot CPU, and is the entry point
* on the secondary CPU.
*/
ENTRY(xen_pvh_early_cpu_init)
mov %rsi, %r11
/* Gather features to see if NX implemented. */
mov $0x80000001, %eax
cpuid
mov %edx, %esi
mov $MSR_EFER, %ecx
rdmsr
bts $_EFER_SCE, %eax
bt $20, %esi
jnc 1f /* No NX, skip setting it */
bts $_EFER_NX, %eax
1: wrmsr
#ifdef CONFIG_SMP
cmp $0, %r11b
jne cpu_bringup_and_idle
#endif
ret
#endif /* CONFIG_XEN_PVH */
.pushsection .text .pushsection .text
.balign PAGE_SIZE .balign PAGE_SIZE
ENTRY(hypercall_page) ENTRY(hypercall_page)
...@@ -124,6 +159,7 @@ NEXT_HYPERCALL(arch_6) ...@@ -124,6 +159,7 @@ NEXT_HYPERCALL(arch_6)
ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
.quad _PAGE_PRESENT; .quad _PAGE_PRESENT) .quad _PAGE_PRESENT; .quad _PAGE_PRESENT)
ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1) ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
ELFNOTE(Xen, XEN_ELFNOTE_MOD_START_PFN, .long 1)
ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, _ASM_PTR __HYPERVISOR_VIRT_START) ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, _ASM_PTR __HYPERVISOR_VIRT_START)
ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, _ASM_PTR 0) ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, _ASM_PTR 0)
......
...@@ -907,22 +907,17 @@ static int connect_ring(struct backend_info *be) ...@@ -907,22 +907,17 @@ static int connect_ring(struct backend_info *be)
return 0; return 0;
} }
/* ** Driver Registration ** */
static const struct xenbus_device_id xen_blkbk_ids[] = { static const struct xenbus_device_id xen_blkbk_ids[] = {
{ "vbd" }, { "vbd" },
{ "" } { "" }
}; };
static struct xenbus_driver xen_blkbk_driver = {
static DEFINE_XENBUS_DRIVER(xen_blkbk, , .ids = xen_blkbk_ids,
.probe = xen_blkbk_probe, .probe = xen_blkbk_probe,
.remove = xen_blkbk_remove, .remove = xen_blkbk_remove,
.otherend_changed = frontend_changed .otherend_changed = frontend_changed
); };
int xen_blkif_xenbus_init(void) int xen_blkif_xenbus_init(void)
{ {
......
...@@ -2055,13 +2055,14 @@ static const struct xenbus_device_id blkfront_ids[] = { ...@@ -2055,13 +2055,14 @@ static const struct xenbus_device_id blkfront_ids[] = {
{ "" } { "" }
}; };
static DEFINE_XENBUS_DRIVER(blkfront, , static struct xenbus_driver blkfront_driver = {
.ids = blkfront_ids,
.probe = blkfront_probe, .probe = blkfront_probe,
.remove = blkfront_remove, .remove = blkfront_remove,
.resume = blkfront_resume, .resume = blkfront_resume,
.otherend_changed = blkback_changed, .otherend_changed = blkback_changed,
.is_ready = blkfront_is_ready, .is_ready = blkfront_is_ready,
); };
static int __init xlblk_init(void) static int __init xlblk_init(void)
{ {
......
...@@ -367,12 +367,13 @@ static const struct xenbus_device_id tpmfront_ids[] = { ...@@ -367,12 +367,13 @@ static const struct xenbus_device_id tpmfront_ids[] = {
}; };
MODULE_ALIAS("xen:vtpm"); MODULE_ALIAS("xen:vtpm");
static DEFINE_XENBUS_DRIVER(tpmfront, , static struct xenbus_driver tpmfront_driver = {
.probe = tpmfront_probe, .ids = tpmfront_ids,
.remove = tpmfront_remove, .probe = tpmfront_probe,
.resume = tpmfront_resume, .remove = tpmfront_remove,
.otherend_changed = backend_changed, .resume = tpmfront_resume,
); .otherend_changed = backend_changed,
};
static int __init xen_tpmfront_init(void) static int __init xen_tpmfront_init(void)
{ {
......
...@@ -365,12 +365,13 @@ static const struct xenbus_device_id xenkbd_ids[] = { ...@@ -365,12 +365,13 @@ static const struct xenbus_device_id xenkbd_ids[] = {
{ "" } { "" }
}; };
static DEFINE_XENBUS_DRIVER(xenkbd, , static struct xenbus_driver xenkbd_driver = {
.ids = xenkbd_ids,
.probe = xenkbd_probe, .probe = xenkbd_probe,
.remove = xenkbd_remove, .remove = xenkbd_remove,
.resume = xenkbd_resume, .resume = xenkbd_resume,
.otherend_changed = xenkbd_backend_changed, .otherend_changed = xenkbd_backend_changed,
); };
static int __init xenkbd_init(void) static int __init xenkbd_init(void)
{ {
......
...@@ -937,22 +937,18 @@ static int read_xenbus_vif_flags(struct backend_info *be) ...@@ -937,22 +937,18 @@ static int read_xenbus_vif_flags(struct backend_info *be)
return 0; return 0;
} }
/* ** Driver Registration ** */
static const struct xenbus_device_id netback_ids[] = { static const struct xenbus_device_id netback_ids[] = {
{ "vif" }, { "vif" },
{ "" } { "" }
}; };
static struct xenbus_driver netback_driver = {
static DEFINE_XENBUS_DRIVER(netback, , .ids = netback_ids,
.probe = netback_probe, .probe = netback_probe,
.remove = netback_remove, .remove = netback_remove,
.uevent = netback_uevent, .uevent = netback_uevent,
.otherend_changed = frontend_changed, .otherend_changed = frontend_changed,
); };
int xenvif_xenbus_init(void) int xenvif_xenbus_init(void)
{ {
......
...@@ -2300,12 +2300,6 @@ static void xennet_sysfs_delif(struct net_device *netdev) ...@@ -2300,12 +2300,6 @@ static void xennet_sysfs_delif(struct net_device *netdev)
#endif /* CONFIG_SYSFS */ #endif /* CONFIG_SYSFS */
static const struct xenbus_device_id netfront_ids[] = {
{ "vif" },
{ "" }
};
static int xennet_remove(struct xenbus_device *dev) static int xennet_remove(struct xenbus_device *dev)
{ {
struct netfront_info *info = dev_get_drvdata(&dev->dev); struct netfront_info *info = dev_get_drvdata(&dev->dev);
...@@ -2338,12 +2332,18 @@ static int xennet_remove(struct xenbus_device *dev) ...@@ -2338,12 +2332,18 @@ static int xennet_remove(struct xenbus_device *dev)
return 0; return 0;
} }
static DEFINE_XENBUS_DRIVER(netfront, , static const struct xenbus_device_id netfront_ids[] = {
{ "vif" },
{ "" }
};
static struct xenbus_driver netfront_driver = {
.ids = netfront_ids,
.probe = netfront_probe, .probe = netfront_probe,
.remove = xennet_remove, .remove = xennet_remove,
.resume = netfront_resume, .resume = netfront_resume,
.otherend_changed = netback_changed, .otherend_changed = netback_changed,
); };
static int __init netif_init(void) static int __init netif_init(void)
{ {
......
...@@ -1136,11 +1136,13 @@ static const struct xenbus_device_id xenpci_ids[] = { ...@@ -1136,11 +1136,13 @@ static const struct xenbus_device_id xenpci_ids[] = {
{""}, {""},
}; };
static DEFINE_XENBUS_DRIVER(xenpci, "pcifront", static struct xenbus_driver xenpci_driver = {
.name = "pcifront",
.ids = xenpci_ids,
.probe = pcifront_xenbus_probe, .probe = pcifront_xenbus_probe,
.remove = pcifront_xenbus_remove, .remove = pcifront_xenbus_remove,
.otherend_changed = pcifront_backend_changed, .otherend_changed = pcifront_backend_changed,
); };
static int __init pcifront_init(void) static int __init pcifront_init(void)
{ {
......
...@@ -587,6 +587,16 @@ config VMWARE_PVSCSI ...@@ -587,6 +587,16 @@ config VMWARE_PVSCSI
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called vmw_pvscsi. module will be called vmw_pvscsi.
config XEN_SCSI_FRONTEND
tristate "XEN SCSI frontend driver"
depends on SCSI && XEN
select XEN_XENBUS_FRONTEND
help
The XEN SCSI frontend driver allows the kernel to access SCSI Devices
within another guest OS (usually Dom0).
Only needed if the kernel is running in a XEN guest and generic
SCSI access to a device is needed.
config HYPERV_STORAGE config HYPERV_STORAGE
tristate "Microsoft Hyper-V virtual storage driver" tristate "Microsoft Hyper-V virtual storage driver"
depends on SCSI && HYPERV depends on SCSI && HYPERV
......
...@@ -141,6 +141,7 @@ obj-$(CONFIG_SCSI_ESAS2R) += esas2r/ ...@@ -141,6 +141,7 @@ obj-$(CONFIG_SCSI_ESAS2R) += esas2r/
obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
obj-$(CONFIG_SCSI_VIRTIO) += virtio_scsi.o obj-$(CONFIG_SCSI_VIRTIO) += virtio_scsi.o
obj-$(CONFIG_VMWARE_PVSCSI) += vmw_pvscsi.o obj-$(CONFIG_VMWARE_PVSCSI) += vmw_pvscsi.o
obj-$(CONFIG_XEN_SCSI_FRONTEND) += xen-scsifront.o
obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o obj-$(CONFIG_HYPERV_STORAGE) += hv_storvsc.o
obj-$(CONFIG_ARM) += arm/ obj-$(CONFIG_ARM) += arm/
......
This diff is collapsed.
...@@ -347,8 +347,6 @@ static int xen_console_remove(struct xencons_info *info) ...@@ -347,8 +347,6 @@ static int xen_console_remove(struct xencons_info *info)
} }
#ifdef CONFIG_HVC_XEN_FRONTEND #ifdef CONFIG_HVC_XEN_FRONTEND
static struct xenbus_driver xencons_driver;
static int xencons_remove(struct xenbus_device *dev) static int xencons_remove(struct xenbus_device *dev)
{ {
return xen_console_remove(dev_get_drvdata(&dev->dev)); return xen_console_remove(dev_get_drvdata(&dev->dev));
...@@ -499,13 +497,14 @@ static const struct xenbus_device_id xencons_ids[] = { ...@@ -499,13 +497,14 @@ static const struct xenbus_device_id xencons_ids[] = {
{ "" } { "" }
}; };
static struct xenbus_driver xencons_driver = {
static DEFINE_XENBUS_DRIVER(xencons, "xenconsole", .name = "xenconsole",
.ids = xencons_ids,
.probe = xencons_probe, .probe = xencons_probe,
.remove = xencons_remove, .remove = xencons_remove,
.resume = xencons_resume, .resume = xencons_resume,
.otherend_changed = xencons_backend_changed, .otherend_changed = xencons_backend_changed,
); };
#endif /* CONFIG_HVC_XEN_FRONTEND */ #endif /* CONFIG_HVC_XEN_FRONTEND */
static int __init xen_hvc_init(void) static int __init xen_hvc_init(void)
......
...@@ -684,12 +684,13 @@ static const struct xenbus_device_id xenfb_ids[] = { ...@@ -684,12 +684,13 @@ static const struct xenbus_device_id xenfb_ids[] = {
{ "" } { "" }
}; };
static DEFINE_XENBUS_DRIVER(xenfb, , static struct xenbus_driver xenfb_driver = {
.ids = xenfb_ids,
.probe = xenfb_probe, .probe = xenfb_probe,
.remove = xenfb_remove, .remove = xenfb_remove,
.resume = xenfb_resume, .resume = xenfb_resume,
.otherend_changed = xenfb_backend_changed, .otherend_changed = xenfb_backend_changed,
); };
static int __init xenfb_init(void) static int __init xenfb_init(void)
{ {
......
...@@ -172,6 +172,15 @@ config XEN_PCIDEV_BACKEND ...@@ -172,6 +172,15 @@ config XEN_PCIDEV_BACKEND
If in doubt, say m. If in doubt, say m.
config XEN_SCSI_BACKEND
tristate "XEN SCSI backend driver"
depends on XEN && XEN_BACKEND && TARGET_CORE
help
The SCSI backend driver allows the kernel to export its SCSI Devices
to other guests via a high-performance shared-memory interface.
Only needed for systems running as XEN driver domains (e.g. Dom0) and
if guests need generic access to SCSI devices.
config XEN_PRIVCMD config XEN_PRIVCMD
tristate tristate
depends on XEN depends on XEN
......
...@@ -36,6 +36,7 @@ obj-$(CONFIG_XEN_ACPI_HOTPLUG_MEMORY) += xen-acpi-memhotplug.o ...@@ -36,6 +36,7 @@ obj-$(CONFIG_XEN_ACPI_HOTPLUG_MEMORY) += xen-acpi-memhotplug.o
obj-$(CONFIG_XEN_ACPI_HOTPLUG_CPU) += xen-acpi-cpuhotplug.o obj-$(CONFIG_XEN_ACPI_HOTPLUG_CPU) += xen-acpi-cpuhotplug.o
obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o obj-$(CONFIG_XEN_ACPI_PROCESSOR) += xen-acpi-processor.o
obj-$(CONFIG_XEN_EFI) += efi.o obj-$(CONFIG_XEN_EFI) += efi.o
obj-$(CONFIG_XEN_SCSI_BACKEND) += xen-scsiback.o
xen-evtchn-y := evtchn.o xen-evtchn-y := evtchn.o
xen-gntdev-y := gntdev.o xen-gntdev-y := gntdev.o
xen-gntalloc-y := gntalloc.o xen-gntalloc-y := gntalloc.o
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <xen/interface/platform.h> #include <xen/interface/platform.h>
#include <xen/xen.h> #include <xen/xen.h>
#include <asm/page.h>
#include <asm/xen/hypercall.h> #include <asm/xen/hypercall.h>
#define INIT_EFI_OP(name) \ #define INIT_EFI_OP(name) \
......
...@@ -900,8 +900,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) ...@@ -900,8 +900,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
return irq; return irq;
} }
static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
unsigned int remote_port) unsigned int remote_port)
{ {
struct evtchn_bind_interdomain bind_interdomain; struct evtchn_bind_interdomain bind_interdomain;
int err; int err;
...@@ -914,6 +914,7 @@ static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain, ...@@ -914,6 +914,7 @@ static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
return err ? : bind_evtchn_to_irq(bind_interdomain.local_port); return err ? : bind_evtchn_to_irq(bind_interdomain.local_port);
} }
EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irq);
static int find_virq(unsigned int virq, unsigned int cpu) static int find_virq(unsigned int virq, unsigned int cpu)
{ {
......
...@@ -592,7 +592,7 @@ static int grow_gnttab_list(unsigned int more_frames) ...@@ -592,7 +592,7 @@ static int grow_gnttab_list(unsigned int more_frames)
return 0; return 0;
grow_nomem: grow_nomem:
for ( ; i >= nr_glist_frames; i--) while (i-- > nr_glist_frames)
free_page((unsigned long) gnttab_list[i]); free_page((unsigned long) gnttab_list[i]);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -719,11 +719,13 @@ static const struct xenbus_device_id xen_pcibk_ids[] = { ...@@ -719,11 +719,13 @@ static const struct xenbus_device_id xen_pcibk_ids[] = {
{""}, {""},
}; };
static DEFINE_XENBUS_DRIVER(xen_pcibk, DRV_NAME, static struct xenbus_driver xen_pcibk_driver = {
.name = DRV_NAME,
.ids = xen_pcibk_ids,
.probe = xen_pcibk_xenbus_probe, .probe = xen_pcibk_xenbus_probe,
.remove = xen_pcibk_xenbus_remove, .remove = xen_pcibk_xenbus_remove,
.otherend_changed = xen_pcibk_frontend_changed, .otherend_changed = xen_pcibk_frontend_changed,
); };
const struct xen_pcibk_backend *__read_mostly xen_pcibk_backend; const struct xen_pcibk_backend *__read_mostly xen_pcibk_backend;
......
This diff is collapsed.
...@@ -259,7 +259,6 @@ static char *error_path(struct xenbus_device *dev) ...@@ -259,7 +259,6 @@ static char *error_path(struct xenbus_device *dev)
static void xenbus_va_dev_error(struct xenbus_device *dev, int err, static void xenbus_va_dev_error(struct xenbus_device *dev, int err,
const char *fmt, va_list ap) const char *fmt, va_list ap)
{ {
int ret;
unsigned int len; unsigned int len;
char *printf_buffer = NULL; char *printf_buffer = NULL;
char *path_buffer = NULL; char *path_buffer = NULL;
...@@ -270,9 +269,7 @@ static void xenbus_va_dev_error(struct xenbus_device *dev, int err, ...@@ -270,9 +269,7 @@ static void xenbus_va_dev_error(struct xenbus_device *dev, int err,
goto fail; goto fail;
len = sprintf(printf_buffer, "%i ", -err); len = sprintf(printf_buffer, "%i ", -err);
ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
dev_err(&dev->dev, "%s\n", printf_buffer); dev_err(&dev->dev, "%s\n", printf_buffer);
...@@ -361,8 +358,8 @@ static void xenbus_switch_fatal(struct xenbus_device *dev, int depth, int err, ...@@ -361,8 +358,8 @@ static void xenbus_switch_fatal(struct xenbus_device *dev, int depth, int err,
* @ring_mfn: mfn of ring to grant * @ring_mfn: mfn of ring to grant
* Grant access to the given @ring_mfn to the peer of the given device. Return * Grant access to the given @ring_mfn to the peer of the given device. Return
* 0 on success, or -errno on error. On error, the device will switch to * a grant reference on success, or -errno on error. On error, the device will
* XenbusStateClosing, and the error will be saved in the store. * switch to XenbusStateClosing, and the error will be saved in the store.
*/ */
int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn) int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn)
{ {
......
...@@ -297,9 +297,13 @@ void xenbus_dev_shutdown(struct device *_dev) ...@@ -297,9 +297,13 @@ void xenbus_dev_shutdown(struct device *_dev)
EXPORT_SYMBOL_GPL(xenbus_dev_shutdown); EXPORT_SYMBOL_GPL(xenbus_dev_shutdown);
int xenbus_register_driver_common(struct xenbus_driver *drv, int xenbus_register_driver_common(struct xenbus_driver *drv,
struct xen_bus_type *bus) struct xen_bus_type *bus,
struct module *owner, const char *mod_name)
{ {
drv->driver.name = drv->name ? drv->name : drv->ids[0].devicetype;
drv->driver.bus = &bus->bus; drv->driver.bus = &bus->bus;
drv->driver.owner = owner;
drv->driver.mod_name = mod_name;
return driver_register(&drv->driver); return driver_register(&drv->driver);
} }
......
...@@ -60,7 +60,9 @@ extern int xenbus_match(struct device *_dev, struct device_driver *_drv); ...@@ -60,7 +60,9 @@ extern int xenbus_match(struct device *_dev, struct device_driver *_drv);
extern int xenbus_dev_probe(struct device *_dev); extern int xenbus_dev_probe(struct device *_dev);
extern int xenbus_dev_remove(struct device *_dev); extern int xenbus_dev_remove(struct device *_dev);
extern int xenbus_register_driver_common(struct xenbus_driver *drv, extern int xenbus_register_driver_common(struct xenbus_driver *drv,
struct xen_bus_type *bus); struct xen_bus_type *bus,
struct module *owner,
const char *mod_name);
extern int xenbus_probe_node(struct xen_bus_type *bus, extern int xenbus_probe_node(struct xen_bus_type *bus,
const char *type, const char *type,
const char *nodename); const char *nodename);
......
...@@ -234,13 +234,15 @@ int xenbus_dev_is_online(struct xenbus_device *dev) ...@@ -234,13 +234,15 @@ int xenbus_dev_is_online(struct xenbus_device *dev)
} }
EXPORT_SYMBOL_GPL(xenbus_dev_is_online); EXPORT_SYMBOL_GPL(xenbus_dev_is_online);
int xenbus_register_backend(struct xenbus_driver *drv) int __xenbus_register_backend(struct xenbus_driver *drv, struct module *owner,
const char *mod_name)
{ {
drv->read_otherend_details = read_frontend_details; drv->read_otherend_details = read_frontend_details;
return xenbus_register_driver_common(drv, &xenbus_backend); return xenbus_register_driver_common(drv, &xenbus_backend,
owner, mod_name);
} }
EXPORT_SYMBOL_GPL(xenbus_register_backend); EXPORT_SYMBOL_GPL(__xenbus_register_backend);
static int backend_probe_and_watch(struct notifier_block *notifier, static int backend_probe_and_watch(struct notifier_block *notifier,
unsigned long event, unsigned long event,
......
...@@ -317,13 +317,15 @@ static void wait_for_devices(struct xenbus_driver *xendrv) ...@@ -317,13 +317,15 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
print_device_status); print_device_status);
} }
int xenbus_register_frontend(struct xenbus_driver *drv) int __xenbus_register_frontend(struct xenbus_driver *drv, struct module *owner,
const char *mod_name)
{ {
int ret; int ret;
drv->read_otherend_details = read_backend_details; drv->read_otherend_details = read_backend_details;
ret = xenbus_register_driver_common(drv, &xenbus_frontend); ret = xenbus_register_driver_common(drv, &xenbus_frontend,
owner, mod_name);
if (ret) if (ret)
return ret; return ret;
...@@ -332,7 +334,7 @@ int xenbus_register_frontend(struct xenbus_driver *drv) ...@@ -332,7 +334,7 @@ int xenbus_register_frontend(struct xenbus_driver *drv)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(xenbus_register_frontend); EXPORT_SYMBOL_GPL(__xenbus_register_frontend);
static DECLARE_WAIT_QUEUE_HEAD(backend_state_wq); static DECLARE_WAIT_QUEUE_HEAD(backend_state_wq);
static int backend_state; static int backend_state;
......
...@@ -28,6 +28,8 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi, ...@@ -28,6 +28,8 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
unsigned long irqflags, unsigned long irqflags,
const char *devname, const char *devname,
void *dev_id); void *dev_id);
int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
unsigned int remote_port);
int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain, int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
unsigned int remote_port, unsigned int remote_port,
irq_handler_t handler, irq_handler_t handler,
......
...@@ -3,6 +3,24 @@ ...@@ -3,6 +3,24 @@
* *
* Definitions used for the Xen ELF notes. * Definitions used for the Xen ELF notes.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2006, Ian Campbell, XenSource Ltd. * Copyright (c) 2006, Ian Campbell, XenSource Ltd.
*/ */
...@@ -18,12 +36,13 @@ ...@@ -18,12 +36,13 @@
* *
* LEGACY indicated the fields in the legacy __xen_guest string which * LEGACY indicated the fields in the legacy __xen_guest string which
* this a note type replaces. * this a note type replaces.
*
* String values (for non-legacy) are NULL terminated ASCII, also known
* as ASCIZ type.
*/ */
/* /*
* NAME=VALUE pair (string). * NAME=VALUE pair (string).
*
* LEGACY: FEATURES and PAE
*/ */
#define XEN_ELFNOTE_INFO 0 #define XEN_ELFNOTE_INFO 0
...@@ -137,9 +156,29 @@ ...@@ -137,9 +156,29 @@
/* /*
* Whether or not the guest supports cooperative suspend cancellation. * Whether or not the guest supports cooperative suspend cancellation.
* This is a numeric value.
*
* Default is 0
*/ */
#define XEN_ELFNOTE_SUSPEND_CANCEL 14 #define XEN_ELFNOTE_SUSPEND_CANCEL 14
/*
* The (non-default) location the initial phys-to-machine map should be
* placed at by the hypervisor (Dom0) or the tools (DomU).
* The kernel must be prepared for this mapping to be established using
* large pages, despite such otherwise not being available to guests.
* The kernel must also be able to handle the page table pages used for
* this mapping not being accessible through the initial mapping.
* (Only x86-64 supports this at present.)
*/
#define XEN_ELFNOTE_INIT_P2M 15
/*
* Whether or not the guest can deal with being passed an initrd not
* mapped through its initial page tables.
*/
#define XEN_ELFNOTE_MOD_START_PFN 16
/* /*
* The features supported by this kernel (numeric). * The features supported by this kernel (numeric).
* *
...@@ -153,6 +192,11 @@ ...@@ -153,6 +192,11 @@
*/ */
#define XEN_ELFNOTE_SUPPORTED_FEATURES 17 #define XEN_ELFNOTE_SUPPORTED_FEATURES 17
/*
* The number of the highest elfnote defined.
*/
#define XEN_ELFNOTE_MAX XEN_ELFNOTE_SUPPORTED_FEATURES
#endif /* __XEN_PUBLIC_ELFNOTE_H__ */ #endif /* __XEN_PUBLIC_ELFNOTE_H__ */
/* /*
......
/******************************************************************************
* vscsiif.h
*
* Based on the blkif.h code.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright(c) FUJITSU Limited 2008.
*/
#ifndef __XEN__PUBLIC_IO_SCSI_H__
#define __XEN__PUBLIC_IO_SCSI_H__
#include "ring.h"
#include "../grant_table.h"
/*
* Feature and Parameter Negotiation
* =================================
* The two halves of a Xen pvSCSI driver utilize nodes within the XenStore to
* communicate capabilities and to negotiate operating parameters. This
* section enumerates these nodes which reside in the respective front and
* backend portions of the XenStore, following the XenBus convention.
*
* Any specified default value is in effect if the corresponding XenBus node
* is not present in the XenStore.
*
* XenStore nodes in sections marked "PRIVATE" are solely for use by the
* driver side whose XenBus tree contains them.
*
*****************************************************************************
* Backend XenBus Nodes
*****************************************************************************
*
*------------------ Backend Device Identification (PRIVATE) ------------------
*
* p-devname
* Values: string
*
* A free string used to identify the physical device (e.g. a disk name).
*
* p-dev
* Values: string
*
* A string specifying the backend device: either a 4-tuple "h:c:t:l"
* (host, controller, target, lun, all integers), or a WWN (e.g.
* "naa.60014054ac780582").
*
* v-dev
* Values: string
*
* A string specifying the frontend device in form of a 4-tuple "h:c:t:l"
* (host, controller, target, lun, all integers).
*
*--------------------------------- Features ---------------------------------
*
* feature-sg-grant
* Values: unsigned [VSCSIIF_SG_TABLESIZE...65535]
* Default Value: 0
*
* Specifies the maximum number of scatter/gather elements in grant pages
* supported. If not set, the backend supports up to VSCSIIF_SG_TABLESIZE
* SG elements specified directly in the request.
*
*****************************************************************************
* Frontend XenBus Nodes
*****************************************************************************
*
*----------------------- Request Transport Parameters -----------------------
*
* event-channel
* Values: unsigned
*
* The identifier of the Xen event channel used to signal activity
* in the ring buffer.
*
* ring-ref
* Values: unsigned
*
* The Xen grant reference granting permission for the backend to map
* the sole page in a single page sized ring buffer.
*
* protocol
* Values: string (XEN_IO_PROTO_ABI_*)
* Default Value: XEN_IO_PROTO_ABI_NATIVE
*
* The machine ABI rules governing the format of all ring request and
* response structures.
*/
/* Requests from the frontend to the backend */
/*
* Request a SCSI operation specified via a CDB in vscsiif_request.cmnd.
* The target is specified via channel, id and lun.
*
* The operation to be performed is specified via a CDB in cmnd[], the length
* of the CDB is in cmd_len. sc_data_direction specifies the direction of data
* (to the device, from the device, or none at all).
*
* If data is to be transferred to or from the device the buffer(s) in the
* guest memory is/are specified via one or multiple scsiif_request_segment
* descriptors each specifying a memory page via a grant_ref_t, a offset into
* the page and the length of the area in that page. All scsiif_request_segment
* areas concatenated form the resulting data buffer used by the operation.
* If the number of scsiif_request_segment areas is not too large (less than
* or equal VSCSIIF_SG_TABLESIZE) the areas can be specified directly in the
* seg[] array and the number of valid scsiif_request_segment elements is to be
* set in nr_segments.
*
* If "feature-sg-grant" in the Xenstore is set it is possible to specify more
* than VSCSIIF_SG_TABLESIZE scsiif_request_segment elements via indirection.
* The maximum number of allowed scsiif_request_segment elements is the value
* of the "feature-sg-grant" entry from Xenstore. When using indirection the
* seg[] array doesn't contain specifications of the data buffers, but
* references to scsiif_request_segment arrays, which in turn reference the
* data buffers. While nr_segments holds the number of populated seg[] entries
* (plus the set VSCSIIF_SG_GRANT bit), the number of scsiif_request_segment
* elements referencing the target data buffers is calculated from the lengths
* of the seg[] elements (the sum of all valid seg[].length divided by the
* size of one scsiif_request_segment structure).
*/
#define VSCSIIF_ACT_SCSI_CDB 1
/*
* Request abort of a running operation for the specified target given by
* channel, id, lun and the operation's rqid in ref_rqid.
*/
#define VSCSIIF_ACT_SCSI_ABORT 2
/*
* Request a device reset of the specified target (channel and id).
*/
#define VSCSIIF_ACT_SCSI_RESET 3
/*
* Preset scatter/gather elements for a following request. Deprecated.
* Keeping the define only to avoid usage of the value "4" for other actions.
*/
#define VSCSIIF_ACT_SCSI_SG_PRESET 4
/*
* Maximum scatter/gather segments per request.
*
* Considering balance between allocating at least 16 "vscsiif_request"
* structures on one page (4096 bytes) and the number of scatter/gather
* elements needed, we decided to use 26 as a magic number.
*
* If "feature-sg-grant" is set, more scatter/gather elements can be specified
* by placing them in one or more (up to VSCSIIF_SG_TABLESIZE) granted pages.
* In this case the vscsiif_request seg elements don't contain references to
* the user data, but to the SG elements referencing the user data.
*/
#define VSCSIIF_SG_TABLESIZE 26
/*
* based on Linux kernel 2.6.18, still valid
* Changing these values requires support of multiple protocols via the rings
* as "old clients" will blindly use these values and the resulting structure
* sizes.
*/
#define VSCSIIF_MAX_COMMAND_SIZE 16
#define VSCSIIF_SENSE_BUFFERSIZE 96
struct scsiif_request_segment {
grant_ref_t gref;
uint16_t offset;
uint16_t length;
};
#define VSCSIIF_SG_PER_PAGE (PAGE_SIZE / sizeof(struct scsiif_request_segment))
/* Size of one request is 252 bytes */
struct vscsiif_request {
uint16_t rqid; /* private guest value, echoed in resp */
uint8_t act; /* command between backend and frontend */
uint8_t cmd_len; /* valid CDB bytes */
uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE]; /* the CDB */
uint16_t timeout_per_command; /* deprecated */
uint16_t channel, id, lun; /* (virtual) device specification */
uint16_t ref_rqid; /* command abort reference */
uint8_t sc_data_direction; /* for DMA_TO_DEVICE(1)
DMA_FROM_DEVICE(2)
DMA_NONE(3) requests */
uint8_t nr_segments; /* Number of pieces of scatter-gather */
/*
* flag in nr_segments: SG elements via grant page
*
* If VSCSIIF_SG_GRANT is set, the low 7 bits of nr_segments specify the number
* of grant pages containing SG elements. Usable if "feature-sg-grant" set.
*/
#define VSCSIIF_SG_GRANT 0x80
struct scsiif_request_segment seg[VSCSIIF_SG_TABLESIZE];
uint32_t reserved[3];
};
/* Size of one response is 252 bytes */
struct vscsiif_response {
uint16_t rqid; /* identifies request */
uint8_t padding;
uint8_t sense_len;
uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE];
int32_t rslt;
uint32_t residual_len; /* request bufflen -
return the value from physical device */
uint32_t reserved[36];
};
DEFINE_RING_TYPES(vscsiif, struct vscsiif_request, struct vscsiif_response);
#endif /*__XEN__PUBLIC_IO_SCSI_H__*/
This diff is collapsed.
...@@ -86,6 +86,7 @@ struct xenbus_device_id ...@@ -86,6 +86,7 @@ struct xenbus_device_id
/* A xenbus driver. */ /* A xenbus driver. */
struct xenbus_driver { struct xenbus_driver {
const char *name; /* defaults to ids[0].devicetype */
const struct xenbus_device_id *ids; const struct xenbus_device_id *ids;
int (*probe)(struct xenbus_device *dev, int (*probe)(struct xenbus_device *dev,
const struct xenbus_device_id *id); const struct xenbus_device_id *id);
...@@ -100,20 +101,22 @@ struct xenbus_driver { ...@@ -100,20 +101,22 @@ struct xenbus_driver {
int (*is_ready)(struct xenbus_device *dev); int (*is_ready)(struct xenbus_device *dev);
}; };
#define DEFINE_XENBUS_DRIVER(var, drvname, methods...) \
struct xenbus_driver var ## _driver = { \
.driver.name = drvname + 0 ?: var ## _ids->devicetype, \
.driver.owner = THIS_MODULE, \
.ids = var ## _ids, ## methods \
}
static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv) static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
{ {
return container_of(drv, struct xenbus_driver, driver); return container_of(drv, struct xenbus_driver, driver);
} }
int __must_check xenbus_register_frontend(struct xenbus_driver *); int __must_check __xenbus_register_frontend(struct xenbus_driver *drv,
int __must_check xenbus_register_backend(struct xenbus_driver *); struct module *owner,
const char *mod_name);
int __must_check __xenbus_register_backend(struct xenbus_driver *drv,
struct module *owner,
const char *mod_name);
#define xenbus_register_frontend(drv) \
__xenbus_register_frontend(drv, THIS_MODULE, KBUILD_MODNAME);
#define xenbus_register_backend(drv) \
__xenbus_register_backend(drv, THIS_MODULE, KBUILD_MODNAME);
void xenbus_unregister_driver(struct xenbus_driver *drv); void xenbus_unregister_driver(struct xenbus_driver *drv);
......
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