bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Signed-off-by: Stefano Stabellini <redacted>
---
drivers/xen/xenbus/xenbus_comms.c | 2 +-
drivers/xen/xenbus/xenbus_probe.c | 62 +++++++++++++++++++++++++-----------
drivers/xen/xenbus/xenbus_xs.c | 1 +
3 files changed, 45 insertions(+), 20 deletions(-)
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;+if(xen_hvm_domain()&&xen_initial_domain())+usage=LOCAL;+if(xen_pv_domain()&&!xen_start_info->store_evtchn)+usage=LOCAL;+if(xen_pv_domain()&&xen_start_info->store_evtchn)+xenstored_ready=1;++switch(usage){+caseLOCAL:err=xenstored_local_init();if(err)gotoout_error;-}-xen_store_interface=mfn_to_virt(xen_store_mfn);+xen_store_interface=mfn_to_virt(xen_store_mfn);+break;+casePV:+xen_store_evtchn=xen_start_info->store_evtchn;+xen_store_mfn=xen_start_info->store_mfn;+xen_store_interface=mfn_to_virt(xen_store_mfn);+break;+caseHVM:+err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);+if(err)+gotoout_error;+xen_store_evtchn=(int)v;+err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);+if(err)+gotoout_error;+xen_store_mfn=(unsignedlong)v;+xen_store_interface=+ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);+break;+default:+pr_warn("Xenstore state unknown\n");+break;}/* Initialize the interface to xenstore. */
All the original Xen headers have xen_ulong_t as unsigned long type, however
when they have been imported in Linux, xen_ulong_t has been replaced with
unsigned long. That might work for x86 and ia64 but it does not for arm.
Bring back xen_ulong_t and let each architecture define xen_ulong_t as they
see fit.
Also explicitly size pointers (__DEFINE_GUEST_HANDLE) to 64 bit.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/xen/interface.h | 8 ++++++--
arch/ia64/include/asm/xen/interface.h | 1 +
arch/x86/include/asm/xen/interface.h | 1 +
include/xen/interface/memory.h | 12 ++++++------
include/xen/interface/physdev.h | 4 ++--
include/xen/interface/version.h | 2 +-
include/xen/interface/xen.h | 6 +++---
7 files changed, 20 insertions(+), 14 deletions(-)
@@ -21,13 +24,14 @@do{\if(sizeof(hnd)==8)\*(uint64_t*)&(hnd)=0;\-(hnd)=val;\+(hnd).p=val;\}while(0)#ifndef __ASSEMBLY__/* Explicitly size integers that represent pfns in the interface with*XensothatwecanhaveoneABIthatworksfor32and64bitguests.*/typedefuint64_txen_pfn_t;+typedefuint64_txen_ulong_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -34,7 +34,7 @@ struct xen_memory_reservation {GUEST_HANDLE(xen_pfn_t)extent_start;/* Number of extents, and size/alignment of each (2^extent_order pages). */-unsignedlongnr_extents;+xen_ulong_tnr_extents;unsignedintextent_order;/*
@@ -148,8 +148,8 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);*/#define XENMEM_machphys_mapping 12structxen_machphys_mapping{-unsignedlongv_start,v_end;/* Start and end virtual addresses. */-unsignedlongmax_mfn;/* Maximum MFN that can be looked up. */+xen_ulong_tv_start,v_end;/* Start and end virtual addresses. */+xen_ulong_tmax_mfn;/* Maximum MFN that can be looked up. */};DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
@@ -169,7 +169,7 @@ struct xen_add_to_physmap {unsignedintspace;/* Index into source mapping space. */-unsignedlongidx;+xen_ulong_tidx;/* GPFN where the source mapping page should appear. */xen_pfn_tgpfn;
@@ -186,7 +186,7 @@ struct xen_translate_gpfn_list {domid_tdomid;/* Length of list. */-unsignedlongnr_gpfns;+xen_ulong_tnr_gpfns;/* List of GPFNs to translate. */GUEST_HANDLE(ulong)gpfn_list;
@@ -108,7 +108,7 @@ struct physdev_set_iobitmap {#define PHYSDEVOP_apic_write 9structphysdev_apic{/* IN */-unsignedlongapic_physbase;+xen_ulong_tapic_physbase;uint32_treg;/* IN or OUT */uint32_tvalue;
Use r12 to pass the hypercall number to the hypervisor.
We need a register to pass the hypercall number because we might not
know it at compile time and HVC only takes an immediate argument.
Among the available registers r12 seems to be the best choice because it
is defined as "intra-procedure call scratch register".
Use the ISS to pass an hypervisor specific tag.
Changes in v2:
- define an HYPERCALL macro for 5 arguments hypercall wrappers, even if
at the moment is unused;
- use ldm instead of pop;
- fix up comments.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/xen/hypercall.h | 50 ++++++++++++++++
arch/arm/xen/Makefile | 2 +-
arch/arm/xen/hypercall.S | 106 ++++++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/include/asm/xen/hypercall.h
create mode 100644 arch/arm/xen/hypercall.S
@@ -246,6 +246,7 @@ endifcore-$(CONFIG_FPE_NWFPE)+=arch/arm/nwfpe/core-$(CONFIG_FPE_FASTFPE)+=$(FASTFPE_OBJ)core-$(CONFIG_VFP)+=arch/arm/vfp/+core-$(CONFIG_XEN)+=arch/arm/xen/# If we have a machine-specific directory, then include it in the build.core-y+=arch/arm/kernel/arch/arm/mm/arch/arm/common/
@@ -0,0 +1,35 @@+#include<xen/xen.h>+#include<xen/interface/xen.h>+#include<xen/interface/memory.h>+#include<xen/platform_pci.h>+#include<asm/xen/hypervisor.h>+#include<asm/xen/hypercall.h>+#include<linux/module.h>++structstart_info_xen_start_info;+structstart_info*xen_start_info=&_xen_start_info;+EXPORT_SYMBOL_GPL(xen_start_info);++enumxen_domain_typexen_domain_type=XEN_NATIVE;+EXPORT_SYMBOL_GPL(xen_domain_type);++structshared_infoxen_dummy_shared_info;+structshared_info*HYPERVISOR_shared_info=(void*)&xen_dummy_shared_info;++DEFINE_PER_CPU(structvcpu_info*,xen_vcpu);++/* XXX: to be removed */+__read_mostlyintxen_have_vector_callback;+EXPORT_SYMBOL_GPL(xen_have_vector_callback);++intxen_platform_pci_unplug=XEN_UNPLUG_ALL;+EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);++intxen_remap_domain_mfn_range(structvm_area_struct*vma,+unsignedlongaddr,+unsignedlongmfn,intnr,+pgprot_tprot,unsigneddomid)+{+return-ENOSYS;+}+EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
sync_bitops functions are equivalent to the SMP implementation of the
original functions, independently from CONFIG_SMP being defined.
We need them because _set_bit etc are not SMP safe if !CONFIG_SMP. But
under Xen you might be communicating with a completely external entity
who might be on another CPU (e.g. two uniprocessor guests communicating
via event channels and grant tables). So we need a variant of the bit
ops which are SMP safe even on a UP kernel.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/sync_bitops.h | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/include/asm/sync_bitops.h
All the original Xen headers have xen_pfn_t as mfn and pfn type, however
when they have been imported in Linux, xen_pfn_t has been replaced with
unsigned long. That might work for x86 and ia64 but it does not for arm.
Bring back xen_pfn_t and let each architecture define xen_pfn_t as they
see fit.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/xen/interface.h | 4 ++++
arch/ia64/include/asm/xen/interface.h | 5 ++++-
arch/x86/include/asm/xen/interface.h | 5 +++++
include/xen/interface/grant_table.h | 4 ++--
include/xen/interface/memory.h | 6 +++---
include/xen/interface/platform.h | 4 ++--
include/xen/interface/xen.h | 6 +++---
include/xen/privcmd.h | 2 --
8 files changed, 23 insertions(+), 13 deletions(-)
@@ -25,6 +25,9 @@}while(0)#ifndef __ASSEMBLY__+/* Explicitly size integers that represent pfns in the interface with+*XensothatwecanhaveoneABIthatworksfor32and64bitguests.*/+typedefuint64_txen_pfn_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -35,6 +38,7 @@ DEFINE_GUEST_HANDLE(long);DEFINE_GUEST_HANDLE(void);DEFINE_GUEST_HANDLE(uint64_t);DEFINE_GUEST_HANDLE(uint32_t);+DEFINE_GUEST_HANDLE(xen_pfn_t);/* Maximum number of virtual CPUs in multi-processor guests. */#define MAX_VIRT_CPUS 1
@@ -67,6 +67,10 @@#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)#ifndef __ASSEMBLY__+/* Explicitly size integers that represent pfns in the public interface+*withXensothatwecouldhaveoneABIthatworksfor32and64bit+*guests.*/+typedefunsignedlongxen_pfn_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -47,6 +47,10 @@#endif#ifndef __ASSEMBLY__+/* Explicitly size integers that represent pfns in the public interface+*withXensothatonARMwecanhaveoneABIthatworksfor32and64+*bitguests.*/+typedefunsignedlongxen_pfn_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -31,7 +31,7 @@ struct xen_memory_reservation {*OUT:GMFNbasesofextentsthatwereallocated*(NB.Thiscommandalsoupdatesthemach_to_phystranslationtable)*/-GUEST_HANDLE(ulong)extent_start;+GUEST_HANDLE(xen_pfn_t)extent_start;/* Number of extents, and size/alignment of each (2^extent_order pages). */unsignedlongnr_extents;
@@ -428,11 +428,11 @@ struct start_info {unsignedlongnr_pages;/* Total pages allocated to this domain. */unsignedlongshared_info;/* MACHINE address of shared info struct. */uint32_tflags;/* SIF_xxx flags. */-unsignedlongstore_mfn;/* MACHINE page number of shared page. */+xen_pfn_tstore_mfn;/* MACHINE page number of shared page. */uint32_tstore_evtchn;/* Event channel for store communication. */union{struct{-unsignedlongmfn;/* MACHINE page number of console page. */+xen_pfn_tmfn;/* MACHINE page number of console page. */uint32_tevtchn;/* Event channel for console page. */}domU;struct{
Check for a "/xen" node in the device tree, if it is present set
xen_domain_type to XEN_HVM_DOMAIN and continue initialization.
Map the real shared info page using XENMEM_add_to_physmap with
XENMAPSPACE_shared_info.
Changes in v2:
- replace pr_info with pr_debug.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/xen/enlighten.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)
@@ -33,3 +36,52 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,return-ENOSYS;}EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);++/*+*==XenDeviceTreeformat==+*-/xennode;+*-compatible"arm,xen";+*-oneinterruptforXeneventnotifications;+*-onememoryregiontomapthegrant_table.+*/+staticint__initxen_guest_init(void)+{+structxen_add_to_physmapxatp;+staticstructshared_info*shared_info_page=0;+structdevice_node*node;++node=of_find_compatible_node(NULL,NULL,"arm,xen");+if(!node){+pr_debug("No Xen support\n");+return0;+}+xen_domain_type=XEN_HVM_DOMAIN;++if(!shared_info_page)+shared_info_page=(structshared_info*)+get_zeroed_page(GFP_KERNEL);+if(!shared_info_page){+pr_err("not enough memory\n");+return-ENOMEM;+}+xatp.domid=DOMID_SELF;+xatp.idx=0;+xatp.space=XENMAPSPACE_shared_info;+xatp.gpfn=__pa(shared_info_page)>>PAGE_SHIFT;+if(HYPERVISOR_memory_op(XENMEM_add_to_physmap,&xatp))+BUG();++HYPERVISOR_shared_info=(structshared_info*)shared_info_page;++/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info+*page,weuseitintheeventchannelupcallandinsomepvclock+*relatedfunctions.Wedon'tneedthevcpu_infoplacement+*optimizationsbecausewedon'tuseanypv_mmuorpv_irqopon+*HVM.+*Thesharedinfocontainsexactly1CPU(thebootCPU).Theguest+*isrequiredtouseVCPUOP_register_vcpu_infotoplacevcpuinfo+*forsecondaryCPUsastheyarebroughtup.*/+per_cpu(xen_vcpu,0)=&HYPERVISOR_shared_info->vcpu_info[0];+return0;+}+core_initcall(xen_guest_init);
ARM Xen guests always use paging in hardware, like PV on HVM guests in
the X86 world.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/xen/page.h | 79 +++++++++++++++++++++++++++++++++++++++
1 files changed, 79 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/include/asm/xen/page.h
Only until we get the balloon driver to work.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/xen/enlighten.c | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
@@ -140,3 +140,21 @@ static int __init xen_init_events(void)return0;}postcore_initcall(xen_init_events);++/* XXX: only until balloon is properly working */+intalloc_xenballooned_pages(intnr_pages,structpage**pages,boolhighmem)+{+*pages=alloc_pages(highmem?GFP_HIGHUSER:GFP_KERNEL,+get_order(nr_pages));+if(*pages==NULL)+return-ENOMEM;+return0;+}+EXPORT_SYMBOL_GPL(alloc_xenballooned_pages);++voidfree_xenballooned_pages(intnr_pages,structpage**pages)+{+kfree(*pages);+*pages=NULL;+}+EXPORT_SYMBOL_GPL(free_xenballooned_pages);
Reset the IRQ_NOAUTOEN and IRQ_NOREQUEST flags that are enabled by
default on ARM. If IRQ_NOAUTOEN is set, __setup_irq doesn't call
irq_startup, that is responsible for calling irq_unmask at startup time.
As a result event channels remain masked.
Signed-off-by: Stefano Stabellini <redacted>
---
drivers/xen/events.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
@@ -836,6 +836,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)structirq_info*info=info_for_irq(irq);WARN_ON(info==NULL||info->type!=IRQT_EVTCHN);}+irq_clear_status_flags(irq,IRQ_NOREQUEST|IRQ_NOAUTOEN);out:mutex_unlock(&irq_mapping_update_lock);
Changes in v2:
- mark Xen guest support on ARM as EXPERIMENTAL.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/Kconfig | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
@@ -1855,6 +1855,16 @@ config DEPRECATED_PARAM_STRUCTThiswasdeprecatedin2001andannouncedtoliveonfor5years.Someoldbootloadersstillusethisway.+configXEN_DOM0+def_booly++configXEN+bool"Xen guest support on ARM (EXPERIMENTAL)"+depends onEXPERIMENTAL&&ARM&&OF+selectXEN_DOM0+help+SayYifyouwanttorunLinuxinaVirtualMachineonXenonARM.+endmenumenu"Boot options"
@@ -109,4 +109,6 @@ int xen_irq_from_gsi(unsigned gsi);/* Determine whether to ignore this IRQ if it is passed to a guest. */intxen_test_irq_shared(intirq);+/* initialize Xen IRQ subsystem */+voidxen_init_IRQ(void);#endif /* _XEN_EVENTS_H */
Use Xen features to figure out if we are privileged.
XENFEAT_dom0 was introduced by 23735 in xen-unstable.hg.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/xen/enlighten.c | 7 +++++++
include/xen/interface/features.h | 3 +++
2 files changed, 10 insertions(+), 0 deletions(-)
@@ -50,6 +50,9 @@/* x86: pirq can be used by HVM guests */#define XENFEAT_hvm_pirqs 10+/* operation as Dom0 is supported */+#define XENFEAT_dom0 11+#define XENFEAT_NR_SUBMAPS 1#endif /* __XEN_PUBLIC_FEATURES_H__ */
This patch removes the "return -ENOSYS" for auto_translated_physmap
guests from privcmd_mmap, thus it allows ARM guests to issue privcmd
mmap calls. However privcmd mmap calls are still going to fail for HVM
and hybrid guests on x86 because the xen_remap_domain_mfn_range
implementation is currently PV only.
Changes in v2:
- better commit message;
- return -EINVAL from xen_remap_domain_mfn_range if
auto_translated_physmap.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/x86/xen/mmu.c | 3 +++
drivers/xen/privcmd.c | 4 ----
2 files changed, 3 insertions(+), 4 deletions(-)
Update struct xen_add_to_physmap to be in sync with Xen's version of the
structure.
The size field was introduced by:
changeset: 24164:707d27fe03e7
user: Jean Guyader [off-list ref]
date: Fri Nov 18 13:42:08 2011 +0000
summary: mm: New XENMEM space, XENMAPSPACE_gmfn_range
According to the comment:
"This new field .size is located in the 16 bits padding between .domid
and .space in struct xen_add_to_physmap to stay compatible with older
versions."
Changes in v2:
- remove erroneous comment in the commit message.
Signed-off-by: Stefano Stabellini <redacted>
---
include/xen/interface/memory.h | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
@@ -163,6 +163,9 @@ struct xen_add_to_physmap {/* Which domain to change the mapping for. */domid_tdomid;+/* Number of pages to go through for gmfn_range */+uint16_tsize;+/* Source mapping space. */#define XENMAPSPACE_shared_info 0 /* shared info page */#define XENMAPSPACE_grant_table 1 /* grant table page */
From: Ian Campbell <redacted>
Do not apply!
This is a simple, hacky implementation of xen_remap_domain_mfn_range,
using XENMAPSPACE_gmfn_foreign.
It should use same interface as hybrid x86.
Changes in v2:
- retain binary compatibility in xen_add_to_physmap: use a union.
Signed-off-by: Ian Campbell <redacted>
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/xen/enlighten.c | 79 +++++++++++++++++++++++++++++++++++++++-
drivers/xen/privcmd.c | 16 +++++----
drivers/xen/xenfs/super.c | 7 ++++
include/xen/interface/memory.h | 15 ++++++--
4 files changed, 105 insertions(+), 12 deletions(-)
@@ -163,12 +163,19 @@ struct xen_add_to_physmap {/* Which domain to change the mapping for. */domid_tdomid;-/* Number of pages to go through for gmfn_range */-uint16_tsize;+union{+/* Number of pages to go through for gmfn_range */+uint16_tsize;+/* IFF gmfn_foreign */+domid_tforeign_domid;+};/* Source mapping space. */-#define XENMAPSPACE_shared_info 0 /* shared info page */-#define XENMAPSPACE_grant_table 1 /* grant table page */+#define XENMAPSPACE_shared_info 0 /* shared info page */+#define XENMAPSPACE_grant_table 1 /* grant table page */+#define XENMAPSPACE_gmfn 2 /* GMFN */+#define XENMAPSPACE_gmfn_range 3 /* GMFN range */+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another guest */unsignedintspace;/* Index into source mapping space. */
Initialize the grant table mapping at the address specified at index 0
in the DT under the /xen node.
After the grant table is initialized, call xenbus_probe (if not dom0).
Changes in v2:
- introduce GRANT_TABLE_PHYSADDR;
- remove unneeded initialization of boot_max_nr_grant_frames.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/xen/enlighten.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
From: David Vrabel <hidden> Date: 2012-08-06 16:23:07
On 06/08/12 15:27, Stefano Stabellini wrote:
quoted hunk
Check for a "/xen" node in the device tree, if it is present set
xen_domain_type to XEN_HVM_DOMAIN and continue initialization.
Map the real shared info page using XENMEM_add_to_physmap with
XENMAPSPACE_shared_info.
Changes in v2:
- replace pr_info with pr_debug.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/xen/enlighten.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)
@@ -33,3 +36,52 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,return-ENOSYS;}EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);++/*+*==XenDeviceTreeformat==+*-/xennode;+*-compatible"arm,xen";+*-oneinterruptforXeneventnotifications;+*-onememoryregiontomapthegrant_table.+*/
These needs to be documented in Documentation/devicetree/bindings/ and
should be sent to the devicetree-discuss mailing list for review.
The node should be called 'hypervisor' I think.
The first word of the compatible string is the vendor/organization that
defined the binding so should be "xen" here. This does give a odd
looking "xen,xen" but we'll have to live with that.
I'd suggest that the DT provided by the hypervisor or tools give the
hypercall ABI version in the compatible string as well. e.g.,
hypervisor {
compatible = "xen,xen-4.3", "xen,xen"
};
I missed the Xen patch that adds this node for dom0. Can you point me
to it?
David
quoted hunk
+static int __init xen_guest_init(void)+{+ struct xen_add_to_physmap xatp;+ static struct shared_info *shared_info_page = 0;+ struct device_node *node;++ node = of_find_compatible_node(NULL, NULL, "arm,xen");+ if (!node) {+ pr_debug("No Xen support\n");+ return 0;+ }+ xen_domain_type = XEN_HVM_DOMAIN;++ if (!shared_info_page)+ shared_info_page = (struct shared_info *)+ get_zeroed_page(GFP_KERNEL);+ if (!shared_info_page) {+ pr_err("not enough memory\n");+ return -ENOMEM;+ }+ xatp.domid = DOMID_SELF;+ xatp.idx = 0;+ xatp.space = XENMAPSPACE_shared_info;+ xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;+ if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))+ BUG();++ HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;++ /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info+ * page, we use it in the event channel upcall and in some pvclock+ * related functions. We don't need the vcpu_info placement+ * optimizations because we don't use any pv_mmu or pv_irq op on+ * HVM.+ * The shared info contains exactly 1 CPU (the boot CPU). The guest+ * is required to use VCPUOP_register_vcpu_info to place vcpu info+ * for secondary CPUs as they are brought up. */+ per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];+ return 0;+}+core_initcall(xen_guest_init);
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:20:12
On Mon, Aug 06, 2012 at 03:27:04PM +0100, Stefano Stabellini wrote:
- Basic hypervisor.h and interface.h definitions.
- Skeleton enlighten.c, set xen_start_info to an empty struct.
- Make xen_initial_domain dependent on the SIF_PRIVILIGED_BIT.
The new code only compiles when CONFIG_XEN is set, that is going to be
added to arch/arm/Kconfig in patch #11 "xen/arm: introduce CONFIG_XEN on
ARM".
You can add my Ack, but do one change pls:
+/* XXX: Move pvclock definitions some place arch independent */
@@ -0,0 +1,35 @@+#include<xen/xen.h>+#include<xen/interface/xen.h>+#include<xen/interface/memory.h>+#include<xen/platform_pci.h>+#include<asm/xen/hypervisor.h>+#include<asm/xen/hypercall.h>+#include<linux/module.h>++structstart_info_xen_start_info;+structstart_info*xen_start_info=&_xen_start_info;+EXPORT_SYMBOL_GPL(xen_start_info);++enumxen_domain_typexen_domain_type=XEN_NATIVE;+EXPORT_SYMBOL_GPL(xen_domain_type);++structshared_infoxen_dummy_shared_info;+structshared_info*HYPERVISOR_shared_info=(void*)&xen_dummy_shared_info;++DEFINE_PER_CPU(structvcpu_info*,xen_vcpu);++/* XXX: to be removed */
s/XXX/TODO/ here, and mention pls why it needs to be removed.
quoted hunk
+__read_mostly int xen_have_vector_callback;+EXPORT_SYMBOL_GPL(xen_have_vector_callback);++int xen_platform_pci_unplug = XEN_UNPLUG_ALL;+EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:23:08
On Mon, Aug 06, 2012 at 03:27:06PM +0100, Stefano Stabellini wrote:
ARM Xen guests always use paging in hardware, like PV on HVM guests in
the X86 world.
Signed-off-by: Stefano Stabellini <redacted>
Ack.. with one nitpick
+/* XXX: this shouldn't be here */
.. but its here b/c the frontend drivers are using it (its rolled in
headers)- even though we won't hit the code path. So for right now
just punt with this.
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:23:16
On Mon, Aug 06, 2012 at 03:27:07PM +0100, Stefano Stabellini wrote:
sync_bitops functions are equivalent to the SMP implementation of the
original functions, independently from CONFIG_SMP being defined.
We need them because _set_bit etc are not SMP safe if !CONFIG_SMP. But
under Xen you might be communicating with a completely external entity
who might be on another CPU (e.g. two uniprocessor guests communicating
via event channels and grant tables). So we need a variant of the bit
ops which are SMP safe even on a UP kernel.
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:27:38
On Mon, Aug 06, 2012 at 03:27:10PM +0100, Stefano Stabellini wrote:
Check for a "/xen" node in the device tree, if it is present set
xen_domain_type to XEN_HVM_DOMAIN and continue initialization.
Map the real shared info page using XENMEM_add_to_physmap with
XENMAPSPACE_shared_info.
Changes in v2:
- replace pr_info with pr_debug.
I second what David mentioned. The other thing is that you are going to
need to rebase this on top of v3.5-rc1, as Olaf's patches have changed
the shared_info_page a bit.
@@ -33,3 +36,52 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,return-ENOSYS;}EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);++/*+*==XenDeviceTreeformat==+*-/xennode;+*-compatible"arm,xen";+*-oneinterruptforXeneventnotifications;+*-onememoryregiontomapthegrant_table.+*/+staticint__initxen_guest_init(void)+{+structxen_add_to_physmapxatp;+staticstructshared_info*shared_info_page=0;+structdevice_node*node;++node=of_find_compatible_node(NULL,NULL,"arm,xen");+if(!node){+pr_debug("No Xen support\n");+return0;+}+xen_domain_type=XEN_HVM_DOMAIN;++if(!shared_info_page)+shared_info_page=(structshared_info*)+get_zeroed_page(GFP_KERNEL);+if(!shared_info_page){+pr_err("not enough memory\n");+return-ENOMEM;+}+xatp.domid=DOMID_SELF;+xatp.idx=0;+xatp.space=XENMAPSPACE_shared_info;+xatp.gpfn=__pa(shared_info_page)>>PAGE_SHIFT;+if(HYPERVISOR_memory_op(XENMEM_add_to_physmap,&xatp))+BUG();++HYPERVISOR_shared_info=(structshared_info*)shared_info_page;++/* xen_vcpu is a pointer to the vcpu_info struct in the shared_info+*page,weuseitintheeventchannelupcallandinsomepvclock+*relatedfunctions.Wedon'tneedthevcpu_infoplacement+*optimizationsbecausewedon'tuseanypv_mmuorpv_irqopon+*HVM.+*Thesharedinfocontainsexactly1CPU(thebootCPU).Theguest+*isrequiredtouseVCPUOP_register_vcpu_infotoplacevcpuinfo+*forsecondaryCPUsastheyarebroughtup.*/+per_cpu(xen_vcpu,0)=&HYPERVISOR_shared_info->vcpu_info[0];+return0;+}+core_initcall(xen_guest_init);
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:28:05
On Mon, Aug 06, 2012 at 03:27:11PM +0100, Stefano Stabellini wrote:
All the original Xen headers have xen_pfn_t as mfn and pfn type, however
when they have been imported in Linux, xen_pfn_t has been replaced with
unsigned long. That might work for x86 and ia64 but it does not for arm.
Bring back xen_pfn_t and let each architecture define xen_pfn_t as they
see fit.
@@ -25,6 +25,9 @@}while(0)#ifndef __ASSEMBLY__+/* Explicitly size integers that represent pfns in the interface with+*XensothatwecanhaveoneABIthatworksfor32and64bitguests.*/+typedefuint64_txen_pfn_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -35,6 +38,7 @@ DEFINE_GUEST_HANDLE(long);DEFINE_GUEST_HANDLE(void);DEFINE_GUEST_HANDLE(uint64_t);DEFINE_GUEST_HANDLE(uint32_t);+DEFINE_GUEST_HANDLE(xen_pfn_t);/* Maximum number of virtual CPUs in multi-processor guests. */#define MAX_VIRT_CPUS 1
@@ -67,6 +67,10 @@#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)#ifndef __ASSEMBLY__+/* Explicitly size integers that represent pfns in the public interface+*withXensothatwecouldhaveoneABIthatworksfor32and64bit+*guests.*/+typedefunsignedlongxen_pfn_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -47,6 +47,10 @@#endif#ifndef __ASSEMBLY__+/* Explicitly size integers that represent pfns in the public interface+*withXensothatonARMwecanhaveoneABIthatworksfor32and64+*bitguests.*/+typedefunsignedlongxen_pfn_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -31,7 +31,7 @@ struct xen_memory_reservation {*OUT:GMFNbasesofextentsthatwereallocated*(NB.Thiscommandalsoupdatesthemach_to_phystranslationtable)*/-GUEST_HANDLE(ulong)extent_start;+GUEST_HANDLE(xen_pfn_t)extent_start;/* Number of extents, and size/alignment of each (2^extent_order pages). */unsignedlongnr_extents;
@@ -428,11 +428,11 @@ struct start_info {unsignedlongnr_pages;/* Total pages allocated to this domain. */unsignedlongshared_info;/* MACHINE address of shared info struct. */uint32_tflags;/* SIF_xxx flags. */-unsignedlongstore_mfn;/* MACHINE page number of shared page. */+xen_pfn_tstore_mfn;/* MACHINE page number of shared page. */uint32_tstore_evtchn;/* Event channel for store communication. */union{struct{-unsignedlongmfn;/* MACHINE page number of console page. */+xen_pfn_tmfn;/* MACHINE page number of console page. */uint32_tevtchn;/* Event channel for console page. */}domU;struct{
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:28:24
On Mon, Aug 06, 2012 at 03:27:12PM +0100, Stefano Stabellini wrote:
All the original Xen headers have xen_ulong_t as unsigned long type, however
when they have been imported in Linux, xen_ulong_t has been replaced with
unsigned long. That might work for x86 and ia64 but it does not for arm.
Bring back xen_ulong_t and let each architecture define xen_ulong_t as they
see fit.
Also explicitly size pointers (__DEFINE_GUEST_HANDLE) to 64 bit.
@@ -21,13 +24,14 @@do{\if(sizeof(hnd)==8)\*(uint64_t*)&(hnd)=0;\-(hnd)=val;\+(hnd).p=val;\}while(0)#ifndef __ASSEMBLY__/* Explicitly size integers that represent pfns in the interface with*XensothatwecanhaveoneABIthatworksfor32and64bitguests.*/typedefuint64_txen_pfn_t;+typedefuint64_txen_ulong_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -34,7 +34,7 @@ struct xen_memory_reservation {GUEST_HANDLE(xen_pfn_t)extent_start;/* Number of extents, and size/alignment of each (2^extent_order pages). */-unsignedlongnr_extents;+xen_ulong_tnr_extents;unsignedintextent_order;/*
@@ -148,8 +148,8 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);*/#define XENMEM_machphys_mapping 12structxen_machphys_mapping{-unsignedlongv_start,v_end;/* Start and end virtual addresses. */-unsignedlongmax_mfn;/* Maximum MFN that can be looked up. */+xen_ulong_tv_start,v_end;/* Start and end virtual addresses. */+xen_ulong_tmax_mfn;/* Maximum MFN that can be looked up. */};DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
@@ -169,7 +169,7 @@ struct xen_add_to_physmap {unsignedintspace;/* Index into source mapping space. */-unsignedlongidx;+xen_ulong_tidx;/* GPFN where the source mapping page should appear. */xen_pfn_tgpfn;
@@ -186,7 +186,7 @@ struct xen_translate_gpfn_list {domid_tdomid;/* Length of list. */-unsignedlongnr_gpfns;+xen_ulong_tnr_gpfns;/* List of GPFNs to translate. */GUEST_HANDLE(ulong)gpfn_list;
@@ -108,7 +108,7 @@ struct physdev_set_iobitmap {#define PHYSDEVOP_apic_write 9structphysdev_apic{/* IN */-unsignedlongapic_physbase;+xen_ulong_tapic_physbase;uint32_treg;/* IN or OUT */uint32_tvalue;
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:31:43
On Mon, Aug 06, 2012 at 03:27:13PM +0100, Stefano Stabellini wrote:
bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Thank you. Lets also CC our friend at NSA who has been doing some work
in that area. Daniel are you OK with this change - will it still make
PV initial domain with with the MiniOS XenBus driver?
Thanks.
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;+if(xen_hvm_domain()&&xen_initial_domain())+usage=LOCAL;+if(xen_pv_domain()&&!xen_start_info->store_evtchn)+usage=LOCAL;+if(xen_pv_domain()&&xen_start_info->store_evtchn)+xenstored_ready=1;++switch(usage){+caseLOCAL:err=xenstored_local_init();if(err)gotoout_error;-}-xen_store_interface=mfn_to_virt(xen_store_mfn);+xen_store_interface=mfn_to_virt(xen_store_mfn);+break;+casePV:+xen_store_evtchn=xen_start_info->store_evtchn;+xen_store_mfn=xen_start_info->store_mfn;+xen_store_interface=mfn_to_virt(xen_store_mfn);+break;+caseHVM:+err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);+if(err)+gotoout_error;+xen_store_evtchn=(int)v;+err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);+if(err)+gotoout_error;+xen_store_mfn=(unsignedlong)v;+xen_store_interface=+ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);+break;+default:+pr_warn("Xenstore state unknown\n");+break;}/* Initialize the interface to xenstore. */
@@ -1855,6 +1855,16 @@ config DEPRECATED_PARAM_STRUCTThiswasdeprecatedin2001andannouncedtoliveonfor5years.Someoldbootloadersstillusethisway.+configXEN_DOM0+def_booly++configXEN+bool"Xen guest support on ARM (EXPERIMENTAL)"+depends onEXPERIMENTAL&&ARM&&OF+selectXEN_DOM0+help+SayYifyouwanttorunLinuxinaVirtualMachineonXenonARM.+endmenumenu"Boot options"
@@ -50,6 +50,9 @@/* x86: pirq can be used by HVM guests */#define XENFEAT_hvm_pirqs 10+/* operation as Dom0 is supported */+#define XENFEAT_dom0 11+#define XENFEAT_NR_SUBMAPS 1#endif /* __XEN_PUBLIC_FEATURES_H__ */
@@ -1808,6 +1816,7 @@ void __init xen_init_IRQ(void) * __acpi_register_gsi can point at the right function */ pci_xen_hvm_init(); } else {+ int rc; struct physdev_pirq_eoi_gmfn eoi_gmfn; irq_ctx_init(smp_processor_id());
@@ -109,4 +109,6 @@ int xen_irq_from_gsi(unsigned gsi);/* Determine whether to ignore this IRQ if it is passed to a guest. */intxen_test_irq_shared(intirq);+/* initialize Xen IRQ subsystem */+voidxen_init_IRQ(void);#endif /* _XEN_EVENTS_H */
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:41:07
On Mon, Aug 06, 2012 at 03:27:19PM +0100, Stefano Stabellini wrote:
Reset the IRQ_NOAUTOEN and IRQ_NOREQUEST flags that are enabled by
default on ARM. If IRQ_NOAUTOEN is set, __setup_irq doesn't call
irq_startup, that is responsible for calling irq_unmask at startup time.
As a result event channels remain masked.
@@ -836,6 +836,7 @@ int bind_evtchn_to_irq(unsigned int evtchn)structirq_info*info=info_for_irq(irq);WARN_ON(info==NULL||info->type!=IRQT_EVTCHN);}+irq_clear_status_flags(irq,IRQ_NOREQUEST|IRQ_NOAUTOEN);out:mutex_unlock(&irq_mapping_update_lock);
@@ -140,3 +140,21 @@ static int __init xen_init_events(void)return0;}postcore_initcall(xen_init_events);++/* XXX: only until balloon is properly working */+intalloc_xenballooned_pages(intnr_pages,structpage**pages,boolhighmem)+{+*pages=alloc_pages(highmem?GFP_HIGHUSER:GFP_KERNEL,+get_order(nr_pages));+if(*pages==NULL)+return-ENOMEM;+return0;+}+EXPORT_SYMBOL_GPL(alloc_xenballooned_pages);++voidfree_xenballooned_pages(intnr_pages,structpage**pages)+{+kfree(*pages);+*pages=NULL;+}+EXPORT_SYMBOL_GPL(free_xenballooned_pages);
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:41:37
On Mon, Aug 06, 2012 at 03:27:21PM +0100, Stefano Stabellini wrote:
This patch removes the "return -ENOSYS" for auto_translated_physmap
guests from privcmd_mmap, thus it allows ARM guests to issue privcmd
mmap calls. However privcmd mmap calls are still going to fail for HVM
and hybrid guests on x86 because the xen_remap_domain_mfn_range
implementation is currently PV only.
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-07 18:43:10
On Mon, Aug 06, 2012 at 03:27:24PM +0100, Stefano Stabellini wrote:
Update struct xen_add_to_physmap to be in sync with Xen's version of the
structure.
The size field was introduced by:
changeset: 24164:707d27fe03e7
user: Jean Guyader [off-list ref]
date: Fri Nov 18 13:42:08 2011 +0000
summary: mm: New XENMEM space, XENMAPSPACE_gmfn_range
According to the comment:
"This new field .size is located in the 16 bits padding between .domid
and .space in struct xen_add_to_physmap to stay compatible with older
versions."
Changes in v2:
Looks good. Let me take this as in my tree to prep it for Mukesh's patches.
@@ -163,6 +163,9 @@ struct xen_add_to_physmap {/* Which domain to change the mapping for. */domid_tdomid;+/* Number of pages to go through for gmfn_range */+uint16_tsize;+/* Source mapping space. */#define XENMAPSPACE_shared_info 0 /* shared info page */#define XENMAPSPACE_grant_table 1 /* grant table page */
@@ -163,12 +163,19 @@ struct xen_add_to_physmap {/* Which domain to change the mapping for. */domid_tdomid;-/* Number of pages to go through for gmfn_range */-uint16_tsize;+union{+/* Number of pages to go through for gmfn_range */+uint16_tsize;+/* IFF gmfn_foreign */+domid_tforeign_domid;+};/* Source mapping space. */-#define XENMAPSPACE_shared_info 0 /* shared info page */-#define XENMAPSPACE_grant_table 1 /* grant table page */+#define XENMAPSPACE_shared_info 0 /* shared info page */+#define XENMAPSPACE_grant_table 1 /* grant table page */+#define XENMAPSPACE_gmfn 2 /* GMFN */+#define XENMAPSPACE_gmfn_range 3 /* GMFN range */+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another guest */unsignedintspace;/* Index into source mapping space. */
From: Daniel De Graaf <hidden> Date: 2012-08-07 19:00:08
On 08/07/2012 02:21 PM, Konrad Rzeszutek Wilk wrote:
On Mon, Aug 06, 2012 at 03:27:13PM +0100, Stefano Stabellini wrote:
quoted
bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Thank you. Lets also CC our friend at NSA who has been doing some work
in that area. Daniel are you OK with this change - will it still make
PV initial domain with with the MiniOS XenBus driver?
Thanks.
That case will work, but what this will break is launching the initial domain
with a Xenstore stub domain already running (see below).
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;
The above is correct for domUs, and is overridden for dom0s:
quoted
+ if (xen_hvm_domain() && xen_initial_domain())+ usage = LOCAL;+ if (xen_pv_domain() && !xen_start_info->store_evtchn)+ usage = LOCAL;
Instead of these checks, I think it should just be:
if (!xen_start_info->store_evtchn)
usage = LOCAL;
Any domain started after xenstore will have store_evtchn set, so if you don't
have this set, you are either going to be running xenstore locally, or will
use the ioctl to change it later (and so should still set up everything as if
it will be running locally).
quoted
+ if (xen_pv_domain() && xen_start_info->store_evtchn)
+ xenstored_ready = 1;
This part can now just be moved unconditionally into case PV.
quoted
++ switch (usage) {+ case LOCAL: err = xenstored_local_init(); if (err) goto out_error;- }- xen_store_interface = mfn_to_virt(xen_store_mfn);+ xen_store_interface = mfn_to_virt(xen_store_mfn);+ break;+ case PV:+ xen_store_evtchn = xen_start_info->store_evtchn;+ xen_store_mfn = xen_start_info->store_mfn;+ xen_store_interface = mfn_to_virt(xen_store_mfn);+ break;+ case HVM:+ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);+ if (err)+ goto out_error;+ xen_store_evtchn = (int)v;+ err = hvm_get_parameter(HVM_PARAM_STORE_PFN, &v);+ if (err)+ goto out_error;+ xen_store_mfn = (unsigned long)v;+ xen_store_interface =+ ioremap(xen_store_mfn << PAGE_SHIFT, PAGE_SIZE);+ break;+ default:+ pr_warn("Xenstore state unknown\n");+ break; } /* Initialize the interface to xenstore. */
From: Dave Martin <hidden> Date: 2012-08-08 12:41:18
On Mon, Aug 06, 2012 at 03:27:05PM +0100, Stefano Stabellini wrote:
Use r12 to pass the hypercall number to the hypervisor.
We need a register to pass the hypercall number because we might not
know it at compile time and HVC only takes an immediate argument.
Among the available registers r12 seems to be the best choice because it
is defined as "intra-procedure call scratch register".
Use the ISS to pass an hypervisor specific tag.
Changes in v2:
- define an HYPERCALL macro for 5 arguments hypercall wrappers, even if
at the moment is unused;
- use ldm instead of pop;
- fix up comments.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/xen/hypercall.h | 50 ++++++++++++++++
arch/arm/xen/Makefile | 2 +-
arch/arm/xen/hypercall.S | 106 ++++++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/include/asm/xen/hypercall.h
create mode 100644 arch/arm/xen/hypercall.S
Consider using my opcode injection helpers patch for this (see
separate repost: [PATCH v2 REPOST 0/4] ARM: opcodes: Facilitate custom
opcode injection), assuming that nobody objects to it. This should mean
that the right opcodes get generated when building a kernel for a big-
endian target for example.
I believe the __HVC(imm) macro which I put in <asm/opcodes-virt.h> as an
example should do what you need in this case.
Note that the preferred entry/exit sequences in such cases are:
stmfd sp!, {r4,lr}
...
ldmfd sp!, {r4,pc}
...but it works either way. I would bother to change it unless you
have other changes to make too.
Cheers
---Dave
Check for a "/xen" node in the device tree, if it is present set
xen_domain_type to XEN_HVM_DOMAIN and continue initialization.
Map the real shared info page using XENMEM_add_to_physmap with
XENMAPSPACE_shared_info.
Changes in v2:
- replace pr_info with pr_debug.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/xen/enlighten.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)
@@ -33,3 +36,52 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,return-ENOSYS;}EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);++/*+*==XenDeviceTreeformat==+*-/xennode;+*-compatible"arm,xen";+*-oneinterruptforXeneventnotifications;+*-onememoryregiontomapthegrant_table.+*/
These needs to be documented in Documentation/devicetree/bindings/ and
should be sent to the devicetree-discuss mailing list for review.
That's a good idea.
The node should be called 'hypervisor' I think.
The first word of the compatible string is the vendor/organization that
defined the binding so should be "xen" here. This does give a odd
looking "xen,xen" but we'll have to live with that.
I'd suggest that the DT provided by the hypervisor or tools give the
hypercall ABI version in the compatible string as well. e.g.,
hypervisor {
compatible = "xen,xen-4.3", "xen,xen"
};
It makes sense, I'll do that.
I missed the Xen patch that adds this node for dom0. Can you point me
to it?
Nope, you didn't miss it: I don't have a patch for Xen yet.
On Mon, Aug 06, 2012 at 03:27:04PM +0100, Stefano Stabellini wrote:
quoted
- Basic hypervisor.h and interface.h definitions.
- Skeleton enlighten.c, set xen_start_info to an empty struct.
- Make xen_initial_domain dependent on the SIF_PRIVILIGED_BIT.
The new code only compiles when CONFIG_XEN is set, that is going to be
added to arch/arm/Kconfig in patch #11 "xen/arm: introduce CONFIG_XEN on
ARM".
You can add my Ack, but do one change pls:
Thanks! I'll make the changes.
quoted
+/* XXX: Move pvclock definitions some place arch independent */
@@ -0,0 +1,35 @@+#include<xen/xen.h>+#include<xen/interface/xen.h>+#include<xen/interface/memory.h>+#include<xen/platform_pci.h>+#include<asm/xen/hypervisor.h>+#include<asm/xen/hypercall.h>+#include<linux/module.h>++structstart_info_xen_start_info;+structstart_info*xen_start_info=&_xen_start_info;+EXPORT_SYMBOL_GPL(xen_start_info);++enumxen_domain_typexen_domain_type=XEN_NATIVE;+EXPORT_SYMBOL_GPL(xen_domain_type);++structshared_infoxen_dummy_shared_info;+structshared_info*HYPERVISOR_shared_info=(void*)&xen_dummy_shared_info;++DEFINE_PER_CPU(structvcpu_info*,xen_vcpu);++/* XXX: to be removed */
s/XXX/TODO/ here, and mention pls why it needs to be removed.
quoted
+__read_mostly int xen_have_vector_callback;+EXPORT_SYMBOL_GPL(xen_have_vector_callback);++int xen_platform_pci_unplug = XEN_UNPLUG_ALL;+EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
On Mon, Aug 06, 2012 at 03:27:06PM +0100, Stefano Stabellini wrote:
quoted
ARM Xen guests always use paging in hardware, like PV on HVM guests in
the X86 world.
Signed-off-by: Stefano Stabellini <redacted>
Ack.. with one nitpick
quoted
+/* XXX: this shouldn't be here */
.. but its here b/c the frontend drivers are using it (its rolled in
headers)- even though we won't hit the code path. So for right now
just punt with this.
On Mon, Aug 06, 2012 at 03:27:12PM +0100, Stefano Stabellini wrote:
quoted
All the original Xen headers have xen_ulong_t as unsigned long type, however
when they have been imported in Linux, xen_ulong_t has been replaced with
unsigned long. That might work for x86 and ia64 but it does not for arm.
Bring back xen_ulong_t and let each architecture define xen_ulong_t as they
see fit.
Also explicitly size pointers (__DEFINE_GUEST_HANDLE) to 64 bit.
Looks ok to me.
Considering that I'll have to change it a bit in the next version
(remove the apic_physbase and multicall_entry changes), I won't add your
acked-by here just yet.
@@ -21,13 +24,14 @@do{\if(sizeof(hnd)==8)\*(uint64_t*)&(hnd)=0;\-(hnd)=val;\+(hnd).p=val;\}while(0)#ifndef __ASSEMBLY__/* Explicitly size integers that represent pfns in the interface with*XensothatwecanhaveoneABIthatworksfor32and64bitguests.*/typedefuint64_txen_pfn_t;+typedefuint64_txen_ulong_t;/* Guest handles for primitive C types. */__DEFINE_GUEST_HANDLE(uchar,unsignedchar);__DEFINE_GUEST_HANDLE(uint,unsignedint);
@@ -34,7 +34,7 @@ struct xen_memory_reservation {GUEST_HANDLE(xen_pfn_t)extent_start;/* Number of extents, and size/alignment of each (2^extent_order pages). */-unsignedlongnr_extents;+xen_ulong_tnr_extents;unsignedintextent_order;/*
@@ -148,8 +148,8 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mfn_list);*/#define XENMEM_machphys_mapping 12structxen_machphys_mapping{-unsignedlongv_start,v_end;/* Start and end virtual addresses. */-unsignedlongmax_mfn;/* Maximum MFN that can be looked up. */+xen_ulong_tv_start,v_end;/* Start and end virtual addresses. */+xen_ulong_tmax_mfn;/* Maximum MFN that can be looked up. */};DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
@@ -169,7 +169,7 @@ struct xen_add_to_physmap {unsignedintspace;/* Index into source mapping space. */-unsignedlongidx;+xen_ulong_tidx;/* GPFN where the source mapping page should appear. */xen_pfn_tgpfn;
@@ -186,7 +186,7 @@ struct xen_translate_gpfn_list {domid_tdomid;/* Length of list. */-unsignedlongnr_gpfns;+xen_ulong_tnr_gpfns;/* List of GPFNs to translate. */GUEST_HANDLE(ulong)gpfn_list;
@@ -108,7 +108,7 @@ struct physdev_set_iobitmap {#define PHYSDEVOP_apic_write 9structphysdev_apic{/* IN */-unsignedlongapic_physbase;+xen_ulong_tapic_physbase;uint32_treg;/* IN or OUT */uint32_tvalue;
On 08/07/2012 02:21 PM, Konrad Rzeszutek Wilk wrote:
quoted
On Mon, Aug 06, 2012 at 03:27:13PM +0100, Stefano Stabellini wrote:
quoted
bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Thank you. Lets also CC our friend at NSA who has been doing some work
in that area. Daniel are you OK with this change - will it still make
PV initial domain with with the MiniOS XenBus driver?
Thanks.
That case will work, but what this will break is launching the initial domain
with a Xenstore stub domain already running (see below).
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;
The above is correct for domUs, and is overridden for dom0s:
quoted
quoted
+ if (xen_hvm_domain() && xen_initial_domain())+ usage = LOCAL;+ if (xen_pv_domain() && !xen_start_info->store_evtchn)+ usage = LOCAL;
Instead of these checks, I think it should just be:
if (!xen_start_info->store_evtchn)
usage = LOCAL;
Any domain started after xenstore will have store_evtchn set, so if you don't
have this set, you are either going to be running xenstore locally, or will
use the ioctl to change it later (and so should still set up everything as if
it will be running locally).
That would be wrong for an HVM dom0 domain (at least on ARM), because
we don't have a start_info page at all.
quoted
quoted
+ if (xen_pv_domain() && xen_start_info->store_evtchn)
+ xenstored_ready = 1;
This part can now just be moved unconditionally into case PV.
What about:
if (xen_pv_domain())
usage = PV;
if (xen_hvm_domain())
usage = HVM;
if (!xen_store_evtchn)
usage = LOCAL;
and moving xenstored_ready in case PV, like you suggested.
From: Daniel De Graaf <hidden> Date: 2012-08-08 17:01:44
On 08/08/2012 12:51 PM, Stefano Stabellini wrote:
On Tue, 7 Aug 2012, Daniel De Graaf wrote:
quoted
On 08/07/2012 02:21 PM, Konrad Rzeszutek Wilk wrote:
quoted
On Mon, Aug 06, 2012 at 03:27:13PM +0100, Stefano Stabellini wrote:
quoted
bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Thank you. Lets also CC our friend at NSA who has been doing some work
in that area. Daniel are you OK with this change - will it still make
PV initial domain with with the MiniOS XenBus driver?
Thanks.
That case will work, but what this will break is launching the initial domain
with a Xenstore stub domain already running (see below).
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;
The above is correct for domUs, and is overridden for dom0s:
quoted
quoted
+ if (xen_hvm_domain() && xen_initial_domain())+ usage = LOCAL;+ if (xen_pv_domain() && !xen_start_info->store_evtchn)+ usage = LOCAL;
Instead of these checks, I think it should just be:
if (!xen_start_info->store_evtchn)
usage = LOCAL;
Any domain started after xenstore will have store_evtchn set, so if you don't
have this set, you are either going to be running xenstore locally, or will
use the ioctl to change it later (and so should still set up everything as if
it will be running locally).
That would be wrong for an HVM dom0 domain (at least on ARM), because
we don't have a start_info page at all.
quoted
quoted
quoted
+ if (xen_pv_domain() && xen_start_info->store_evtchn)
+ xenstored_ready = 1;
This part can now just be moved unconditionally into case PV.
What about:
if (xen_pv_domain())
usage = PV;
if (xen_hvm_domain())
usage = HVM;
if (!xen_store_evtchn)
usage = LOCAL;
and moving xenstored_ready in case PV, like you suggested.
That looks correct, but you'd need to split up the switch statement in
order to populate xen_store_evtchn before that last condition, which
ends up pretty much eliminating the usage variable.
On 08/07/2012 02:21 PM, Konrad Rzeszutek Wilk wrote:
quoted
On Mon, Aug 06, 2012 at 03:27:13PM +0100, Stefano Stabellini wrote:
quoted
bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Thank you. Lets also CC our friend at NSA who has been doing some work
in that area. Daniel are you OK with this change - will it still make
PV initial domain with with the MiniOS XenBus driver?
Thanks.
That case will work, but what this will break is launching the initial domain
with a Xenstore stub domain already running (see below).
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;
The above is correct for domUs, and is overridden for dom0s:
quoted
quoted
+ if (xen_hvm_domain() && xen_initial_domain())+ usage = LOCAL;+ if (xen_pv_domain() && !xen_start_info->store_evtchn)+ usage = LOCAL;
Instead of these checks, I think it should just be:
if (!xen_start_info->store_evtchn)
usage = LOCAL;
Any domain started after xenstore will have store_evtchn set, so if you don't
have this set, you are either going to be running xenstore locally, or will
use the ioctl to change it later (and so should still set up everything as if
it will be running locally).
That would be wrong for an HVM dom0 domain (at least on ARM), because
we don't have a start_info page at all.
quoted
quoted
quoted
+ if (xen_pv_domain() && xen_start_info->store_evtchn)
+ xenstored_ready = 1;
This part can now just be moved unconditionally into case PV.
What about:
if (xen_pv_domain())
usage = PV;
if (xen_hvm_domain())
usage = HVM;
if (!xen_store_evtchn)
usage = LOCAL;
and moving xenstored_ready in case PV, like you suggested.
That looks correct, but you'd need to split up the switch statement in
order to populate xen_store_evtchn before that last condition, which
ends up pretty much eliminating the usage variable.
Going back to what you wrote in the previous email, in what way this
patch breaks the case when an initial domain is started after a Xenstore
stub domain?
Assuming that we are talking about a PV initial domain on x86, the
following check
if (xen_pv_domain() && !xen_start_info->store_evtchn)
usage = LOCAL;
will return false (because store_evtchn is set), therefore usage will
remain set to PV.
And the check:
if (xen_pv_domain() && xen_start_info->store_evtchn)
xenstored_ready = 1;
will return true so xenstored_ready is going to be set to 1.
On Mon, Aug 06, 2012 at 03:27:24PM +0100, Stefano Stabellini wrote:
quoted
Update struct xen_add_to_physmap to be in sync with Xen's version of the
structure.
The size field was introduced by:
changeset: 24164:707d27fe03e7
user: Jean Guyader [off-list ref]
date: Fri Nov 18 13:42:08 2011 +0000
summary: mm: New XENMEM space, XENMAPSPACE_gmfn_range
According to the comment:
"This new field .size is located in the 16 bits padding between .domid
and .space in struct xen_add_to_physmap to stay compatible with older
versions."
Changes in v2:
Looks good. Let me take this as in my tree to prep it for Mukesh's patches.
OK.
Beware that patch #23 is going to modify xen_add_to_physmap again to
replace .size with a union.
@@ -163,6 +163,9 @@ struct xen_add_to_physmap {/* Which domain to change the mapping for. */domid_tdomid;+/* Number of pages to go through for gmfn_range */+uint16_tsize;+/* Source mapping space. */#define XENMAPSPACE_shared_info 0 /* shared info page */#define XENMAPSPACE_grant_table 1 /* grant table page */
From: Daniel De Graaf <hidden> Date: 2012-08-08 17:34:01
On 08/08/2012 01:19 PM, Stefano Stabellini wrote:
On Wed, 8 Aug 2012, Daniel De Graaf wrote:
quoted
On 08/08/2012 12:51 PM, Stefano Stabellini wrote:
quoted
On Tue, 7 Aug 2012, Daniel De Graaf wrote:
quoted
On 08/07/2012 02:21 PM, Konrad Rzeszutek Wilk wrote:
quoted
On Mon, Aug 06, 2012 at 03:27:13PM +0100, Stefano Stabellini wrote:
quoted
bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Thank you. Lets also CC our friend at NSA who has been doing some work
in that area. Daniel are you OK with this change - will it still make
PV initial domain with with the MiniOS XenBus driver?
Thanks.
That case will work, but what this will break is launching the initial domain
with a Xenstore stub domain already running (see below).
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;
The above is correct for domUs, and is overridden for dom0s:
quoted
quoted
+ if (xen_hvm_domain() && xen_initial_domain())+ usage = LOCAL;+ if (xen_pv_domain() && !xen_start_info->store_evtchn)+ usage = LOCAL;
Instead of these checks, I think it should just be:
if (!xen_start_info->store_evtchn)
usage = LOCAL;
Any domain started after xenstore will have store_evtchn set, so if you don't
have this set, you are either going to be running xenstore locally, or will
use the ioctl to change it later (and so should still set up everything as if
it will be running locally).
That would be wrong for an HVM dom0 domain (at least on ARM), because
we don't have a start_info page at all.
quoted
quoted
quoted
+ if (xen_pv_domain() && xen_start_info->store_evtchn)
+ xenstored_ready = 1;
This part can now just be moved unconditionally into case PV.
What about:
if (xen_pv_domain())
usage = PV;
if (xen_hvm_domain())
usage = HVM;
if (!xen_store_evtchn)
usage = LOCAL;
and moving xenstored_ready in case PV, like you suggested.
That looks correct, but you'd need to split up the switch statement in
order to populate xen_store_evtchn before that last condition, which
ends up pretty much eliminating the usage variable.
Going back to what you wrote in the previous email, in what way this
patch breaks the case when an initial domain is started after a Xenstore
stub domain?
Assuming that we are talking about a PV initial domain on x86, the
following check
if (xen_pv_domain() && !xen_start_info->store_evtchn)
usage = LOCAL;
will return false (because store_evtchn is set), therefore usage will
remain set to PV.
And the check:
if (xen_pv_domain() && xen_start_info->store_evtchn)
xenstored_ready = 1;
will return true so xenstored_ready is going to be set to 1.
Right, the original patch didn't break anything with PV domains. The case
it doesn't handle is an HVM initial domain with an already-running
Xenstore domain; I think this applies both to ARM and hybrid/PVH on x86.
In that case, usage would be set to LOCAL instead of HVM.
As a side note: the value of xen_initial_domain() shouldn't be connected to
determining if xenstore is running locally or not.
--
Daniel De Graaf
National Security Agency
On 08/07/2012 02:21 PM, Konrad Rzeszutek Wilk wrote:
quoted
On Mon, Aug 06, 2012 at 03:27:13PM +0100, Stefano Stabellini wrote:
quoted
bind_evtchn_to_irqhandler can legitimately return 0 (irq 0): it is not
an error.
If Linux is running as an HVM domain and is running as Dom0, use
xenstored_local_init to initialize the xenstore page and event channel.
Changes in v2:
- refactor xenbus_init.
Thank you. Lets also CC our friend at NSA who has been doing some work
in that area. Daniel are you OK with this change - will it still make
PV initial domain with with the MiniOS XenBus driver?
Thanks.
That case will work, but what this will break is launching the initial domain
with a Xenstore stub domain already running (see below).
@@ -719,37 +719,61 @@ static int __init xenstored_local_init(void)returnerr;}+enumxenstore_init{+UNKNOWN,+PV,+HVM,+LOCAL,+};staticint__initxenbus_init(void){interr=0;+enumxenstore_initusage=UNKNOWN;+uint64_tv=0;if(!xen_domain())return-ENODEV;xenbus_ring_ops_init();-if(xen_hvm_domain()){-uint64_tv=0;-err=hvm_get_parameter(HVM_PARAM_STORE_EVTCHN,&v);-if(err)-gotoout_error;-xen_store_evtchn=(int)v;-err=hvm_get_parameter(HVM_PARAM_STORE_PFN,&v);-if(err)-gotoout_error;-xen_store_mfn=(unsignedlong)v;-xen_store_interface=ioremap(xen_store_mfn<<PAGE_SHIFT,PAGE_SIZE);-}else{-xen_store_evtchn=xen_start_info->store_evtchn;-xen_store_mfn=xen_start_info->store_mfn;-if(xen_store_evtchn)-xenstored_ready=1;-else{+if(xen_pv_domain())+usage=PV;+if(xen_hvm_domain())+usage=HVM;
The above is correct for domUs, and is overridden for dom0s:
quoted
quoted
+ if (xen_hvm_domain() && xen_initial_domain())+ usage = LOCAL;+ if (xen_pv_domain() && !xen_start_info->store_evtchn)+ usage = LOCAL;
Instead of these checks, I think it should just be:
if (!xen_start_info->store_evtchn)
usage = LOCAL;
Any domain started after xenstore will have store_evtchn set, so if you don't
have this set, you are either going to be running xenstore locally, or will
use the ioctl to change it later (and so should still set up everything as if
it will be running locally).
That would be wrong for an HVM dom0 domain (at least on ARM), because
we don't have a start_info page at all.
quoted
quoted
quoted
+ if (xen_pv_domain() && xen_start_info->store_evtchn)
+ xenstored_ready = 1;
This part can now just be moved unconditionally into case PV.
What about:
if (xen_pv_domain())
usage = PV;
if (xen_hvm_domain())
usage = HVM;
if (!xen_store_evtchn)
usage = LOCAL;
and moving xenstored_ready in case PV, like you suggested.
That looks correct, but you'd need to split up the switch statement in
order to populate xen_store_evtchn before that last condition, which
ends up pretty much eliminating the usage variable.
Going back to what you wrote in the previous email, in what way this
patch breaks the case when an initial domain is started after a Xenstore
stub domain?
Assuming that we are talking about a PV initial domain on x86, the
following check
if (xen_pv_domain() && !xen_start_info->store_evtchn)
usage = LOCAL;
will return false (because store_evtchn is set), therefore usage will
remain set to PV.
And the check:
if (xen_pv_domain() && xen_start_info->store_evtchn)
xenstored_ready = 1;
will return true so xenstored_ready is going to be set to 1.
Right, the original patch didn't break anything with PV domains. The case
it doesn't handle is an HVM initial domain with an already-running
Xenstore domain; I think this applies both to ARM and hybrid/PVH on x86.
In that case, usage would be set to LOCAL instead of HVM.
Right, however if I am not mistaken there is no such thing as an HVM
dom0 right now on x86 and hybrid/PVH is probably going to return true on
xen_pv_domain() and false on xen_hvm_domain().
In the ARM case, given that we don't have a start_info page, we would
need another way to figure out whether a xenstore stub domain is already
running, so I think we can just postpone the solution of that problem
for now.
Uh, that is bold. One global to rule them all, eh? Should you make
it at least:
static DEFINE_PER_CPU(int, xen_events_irq);
?
That is an interesting observation.
Currently Xen is using a per-cpu interrupt (a PPI, using the GIC
terminology), and it makes sense so that we can receive event
notifications on multiple vcpus independently.
The irq range 16-31 is reserved for PPIs and I am assuming that Xen will
be able to find one spare, the same one, for all vcpus.
In fact the third field corresponding to the interrupt in the DT (0xf08
in my dts) contains the cpu mask and it is set to 0xf (the maximum)
right now.
Maybe I should just BUG_ON(xen_events_irq > 31 || xen_events_irq < 16)?
The versioning of the hypervisor node on the DT is going to help us make
any changes to the interface in the future.
On Mon, Aug 06, 2012 at 03:27:05PM +0100, Stefano Stabellini wrote:
quoted
Use r12 to pass the hypercall number to the hypervisor.
We need a register to pass the hypercall number because we might not
know it at compile time and HVC only takes an immediate argument.
Among the available registers r12 seems to be the best choice because it
is defined as "intra-procedure call scratch register".
Use the ISS to pass an hypervisor specific tag.
Changes in v2:
- define an HYPERCALL macro for 5 arguments hypercall wrappers, even if
at the moment is unused;
- use ldm instead of pop;
- fix up comments.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/xen/hypercall.h | 50 ++++++++++++++++
arch/arm/xen/Makefile | 2 +-
arch/arm/xen/hypercall.S | 106 ++++++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/include/asm/xen/hypercall.h
create mode 100644 arch/arm/xen/hypercall.S
Consider using my opcode injection helpers patch for this (see
separate repost: [PATCH v2 REPOST 0/4] ARM: opcodes: Facilitate custom
opcode injection), assuming that nobody objects to it. This should mean
that the right opcodes get generated when building a kernel for a big-
endian target for example.
I believe the __HVC(imm) macro which I put in <asm/opcodes-virt.h> as an
example should do what you need in this case.
Sure I can do that. Maybe I'll add another patch at the end of my series
to replace xen_hvc with __HVC(0xEA1), so that it remains independent
from your series.
I have learned through experience that avoiding cross patch series
dependencies help to reduce the amount of headaches during merge windows
:)
Note that the preferred entry/exit sequences in such cases are:
stmfd sp!, {r4,lr}
...
ldmfd sp!, {r4,pc}
...but it works either way. I would bother to change it unless you
have other changes to make too.
Wouldn't this needlessly save and restore one more register (lr) to the
stack?
I would try to keep the hypercall wrappers as small as possible...
From: Dave Martin <hidden> Date: 2012-08-09 16:50:31
On Thu, Aug 09, 2012 at 04:37:24PM +0100, Stefano Stabellini wrote:
On Wed, 8 Aug 2012, Dave Martin wrote:
quoted
On Mon, Aug 06, 2012 at 03:27:05PM +0100, Stefano Stabellini wrote:
quoted
Use r12 to pass the hypercall number to the hypervisor.
We need a register to pass the hypercall number because we might not
know it at compile time and HVC only takes an immediate argument.
Among the available registers r12 seems to be the best choice because it
is defined as "intra-procedure call scratch register".
Use the ISS to pass an hypervisor specific tag.
Changes in v2:
- define an HYPERCALL macro for 5 arguments hypercall wrappers, even if
at the moment is unused;
- use ldm instead of pop;
- fix up comments.
Signed-off-by: Stefano Stabellini <redacted>
---
arch/arm/include/asm/xen/hypercall.h | 50 ++++++++++++++++
arch/arm/xen/Makefile | 2 +-
arch/arm/xen/hypercall.S | 106 ++++++++++++++++++++++++++++++++++
3 files changed, 157 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/include/asm/xen/hypercall.h
create mode 100644 arch/arm/xen/hypercall.S
Consider using my opcode injection helpers patch for this (see
separate repost: [PATCH v2 REPOST 0/4] ARM: opcodes: Facilitate custom
opcode injection), assuming that nobody objects to it. This should mean
that the right opcodes get generated when building a kernel for a big-
endian target for example.
I believe the __HVC(imm) macro which I put in <asm/opcodes-virt.h> as an
example should do what you need in this case.
Sure I can do that. Maybe I'll add another patch at the end of my series
to replace xen_hvc with __HVC(0xEA1), so that it remains independent
from your series.
I have learned through experience that avoiding cross patch series
dependencies help to reduce the amount of headaches during merge windows
:)
I agree. I'll let you know when my patch gets merged -- in the meantime,
it makes sense for you to keep your existing code.
Note that the preferred entry/exit sequences in such cases are:
stmfd sp!, {r4,lr}
...
ldmfd sp!, {r4,pc}
...but it works either way. I would bother to change it unless you
have other changes to make too.
Wouldn't this needlessly save and restore one more register (lr) to the
stack?
I would try to keep the hypercall wrappers as small as possible...
Argh, ignore me -- I was hallucinating for some reason that we actually
needed to save lr, but we don't.
Using the stmfd/ldmfd mnemonics might still be nicer than stmdb/ldm, since
the fd suffix makes the stack semantics more obvious, and the code
looks more symmetrical. This was the conventional way to write these
mnemonics before the "push" and "pop" mnemonics existed.
That's purely cosmetic, though.
Cheers
---Dave
From: Konrad Rzeszutek Wilk <hidden> Date: 2012-08-09 17:04:34
quoted
Right, the original patch didn't break anything with PV domains. The case
it doesn't handle is an HVM initial domain with an already-running
Xenstore domain; I think this applies both to ARM and hybrid/PVH on x86.
In that case, usage would be set to LOCAL instead of HVM.
Right, however if I am not mistaken there is no such thing as an HVM
dom0 right now on x86 and hybrid/PVH is probably going to return true on
xen_pv_domain() and false on xen_hvm_domain().
The other way around. HVM = true, PV = false.
Mukesh, correct me if I am wrong pls.
In the ARM case, given that we don't have a start_info page, we would
need another way to figure out whether a xenstore stub domain is already
running, so I think we can just postpone the solution of that problem
for now.