Re: [Xen-devel] [PATCH v10 05/25] x86: refactor psr: L3 CAT: implement CPU init and free flow.

2017-04-05 Thread Yi Sun
On 17-04-05 09:10:58, Jan Beulich wrote:
> >>> On 01.04.17 at 15:53,  wrote:
> > @@ -76,7 +79,7 @@ struct feat_node {
> >   *
> >   * Feature independent HW info and common values are also defined in 
> > it.
> >   */
> > -const struct feat_props {
> > +struct feat_props {
> 
> As said before, the const here should stay. The init-time writing
> to the structure can be done without going through this pointer.
> 
'feat_props' contains 'cos_max' and 'cbm_len' in this version. I have to assign
values to them in 'cat_init_feature'. So, I removed the 'const'.

Anyway, this structure will be moved out as a standalone struct to define a
static pointer array of 'props'. The 'cos_max' and 'cbm_len' will be moved to
'struct feat_node'.

> > +static void free_socket_resources(unsigned int socket)
> > +{
> > +unsigned int i;
> > +struct psr_socket_info *info = socket_info + socket;
> > +
> > +if ( !info )
> > +return;
> > +
> > +/*
> > + * Free resources of features. The global feature object, e.g. 
> > feat_l3_cat,
> > + * may not be freed here if it is not added into array. It is simply 
> > being
> > + * kept until the next CPU online attempt.
> > + */
> > +for ( i = 0; i < PSR_SOCKET_MAX_FEAT; i++ )
> > +{
> > +if ( !info->features[i] )
> > +continue;
> > +
> > +xfree(info->features[i]);
> > +info->features[i] = NULL;
> 
> There's no need for the if() here. And I'm sure this was pointed out
> already (perhaps in a different context).
> 
There may be NULL member in features array. Features array contains all
features, including L3 CAT, CDP and L2 CAT. But on some machines, they
may only support L3 CAT but do not support CDP and L2 CAT. So, the features
array only has L3 CAT member in it and all other members are all NULL. That
is the reason we must check if the member is NULL or not.

> > +static bool feat_init_done(const struct psr_socket_info *info)
> > +{
> > +unsigned int i;
> > +
> > +for ( i = 0; i < PSR_SOCKET_MAX_FEAT; i++ )
> > +{
> > +if ( !info->features[i] )
> > +continue;
> > +
> > +return true;
> > +}
> > +
> > +return false;
> > +}
> 
> At the first glance this is a very strange function.
> 
I used 'feat_mask' before to check if any feature has been initialized.
Per your comment in later patch, I want to define a flag to represent it.
Is that acceptable to you?

> > +/* CAT common functions implementation. */
> > +static void cat_init_feature(const struct cpuid_leaf *regs,
> > + struct feat_node *feat,
> > + struct psr_socket_info *info,
> > + enum psr_feat_type type)
> > +{
> > +unsigned int socket, i;
> > +
> > +/* No valid value so do not enable feature. */
> > +if ( !regs->a || !regs->d )
> > +return;
> > +
> > +feat->props->cbm_len = (regs->a & CAT_CBM_LEN_MASK) + 1;
> > +feat->props->cos_max = min(opt_cos_max, regs->d & CAT_COS_MAX_MASK);
> > +
> > +switch ( type )
> > +{
> > +case PSR_SOCKET_L3_CAT:
> > +/* cos=0 is reserved as default cbm(all bits within cbm_len are 
> > 1). */
> > +feat->cos_reg_val[0] = cat_default_val(feat->props->cbm_len);
> > +
> > +/*
> > + * To handle cpu offline and then online case, we need restore 
> > MSRs to
> > + * default values.
> > + */
> > +for ( i = 1; i <= feat->props->cos_max; i++ )
> > +{
> > +wrmsrl(MSR_IA32_PSR_L3_MASK(i), feat->cos_reg_val[0]);
> > +feat->cos_reg_val[i] = feat->cos_reg_val[0];
> > +}
> 
> I continue to have difficulty with this: Why is offline-then-online
> any different from first-time-online? Why wouldn't setting the

May remove this comment. Per current codes, the MSRs are written to default
values no matter first time or not.

> registers to their intended values not be taken care of by
> context switch code, once vCPU-s get scheduled onto the newly
> onlined CPU?
> 
cat_init_feature is only called when the first CPU on a socket is online.
The MSRs to set are per socket. So, we only need set it once when socket
is online.

> > +break;
> > +
> > +default:
> > +return;
> > +}
> > +
> > +/* Add this feature into array. */
> > +info->features[type] = feat;
> > +
> > +socket = cpu_to_socket(smp_processor_id());
> 
> No need for this variable, and definitely no need to do the
> assignment ahead of ...
> > +if ( !opt_cpu_info )
> > +return;
> 
> ... this.

Ok, will remove socket to directly use 'cpu_to_socket(smp_processor_id())'.

> 
> >  static void psr_cpu_init(void)
> >  {
> > +struct psr_socket_info *info;
> > +unsigned int socket;
> > +unsigned int cpu = smp_processor_id();
> > +struct feat_node *feat;
> > +struct cpuid_leaf regs;
> > +
> > +if ( !psr_alloc_feat_enabled() 

[Xen-devel] [PATCH 2/2] xen/mce: fix static variable 'severity_cpu'

2017-04-05 Thread Haozhong Zhang
1. Distinguish 'severity_cpu' used in mcheck_cmn_handler() and
   mce_softirq(), which should be different variables. Otherwise, they
   may interfere with each other if MC# comes during mce_softirq().
2. Always (re-)initialize 'severity_cpu' to clear historical information.

Signed-off-by: Haozhong Zhang 
---
 xen/arch/x86/cpu/mcheck/mce.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
index 7618120..d9ab80a 100644
--- a/xen/arch/x86/cpu/mcheck/mce.c
+++ b/xen/arch/x86/cpu/mcheck/mce.c
@@ -177,7 +177,7 @@ void mce_need_clearbank_register(mce_need_clearbank_t 
cbfunc)
 
 static struct mce_softirq_barrier mce_inside_bar, mce_severity_bar;
 static struct mce_softirq_barrier mce_trap_bar;
-static struct mce_softirq_barrier mce_handler_init_bar;
+static struct mce_softirq_barrier mce_handler_init_bar, mce_softirq_init_bar;
 
 /*
  * mce_logout_lock should only be used in the trap handler,
@@ -187,8 +187,6 @@ static struct mce_softirq_barrier mce_handler_init_bar;
  */
 static DEFINE_SPINLOCK(mce_logout_lock);
 
-static atomic_t severity_cpu = ATOMIC_INIT(-1);
-
 const struct mca_error_handler *__read_mostly mce_dhandlers;
 const struct mca_error_handler *__read_mostly mce_uhandlers;
 unsigned int __read_mostly mce_dhandler_num;
@@ -452,7 +450,7 @@ static int mce_urgent_action(const struct cpu_user_regs 
*regs,
 /* Shared #MC handler. */
 void mcheck_cmn_handler(const struct cpu_user_regs *regs)
 {
-static atomic_t found_error;
+static atomic_t severity_cpu, found_error;
 static cpumask_t mce_fatal_cpus;
 struct mca_banks *bankmask = mca_allbanks;
 struct mca_banks *clear_bank = __get_cpu_var(mce_clear_banks);
@@ -461,6 +459,7 @@ void mcheck_cmn_handler(const struct cpu_user_regs *regs)
 struct mca_summary bs;
 
 mce_barrier_enter(_handler_init_bar);
+atomic_set(_cpu, -1);
 atomic_set(_error, 0);
 cpumask_clear(_fatal_cpus);
 mce_barrier_exit(_handler_init_bar);
@@ -1704,11 +1703,16 @@ static int mce_delayed_action(mctelem_cookie_t mctc)
 /* Softirq Handler for this MCE# processing */
 static void mce_softirq(void)
 {
+static atomic_t severity_cpu;
 int cpu = smp_processor_id();
 unsigned int workcpu;
 
 mce_printk(MCE_VERBOSE, "CPU%d enter softirq\n", cpu);
 
+mce_barrier_enter(_softirq_init_bar);
+atomic_set(_cpu, -1);
+mce_barrier_exit(_softirq_init_bar);
+
 mce_barrier_enter(_inside_bar);
 
 /*
@@ -1774,6 +1778,7 @@ void mce_handler_init(void)
 mce_barrier_init(_severity_bar);
 mce_barrier_init(_trap_bar);
 mce_barrier_init(_handler_init_bar);
+mce_barrier_init(_softirq_init_bar);
 spin_lock_init(_logout_lock);
 open_softirq(MACHINE_CHECK_SOFTIRQ, mce_softirq);
 }
-- 
2.10.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH 1/2] xen/mce: fix static variables 'found_error' and 'mce_fatal_cpus'

2017-04-05 Thread Haozhong Zhang
1. Move them into mcheck_cmn_handler() which is their only user.
2. Always (re-)initialize them to clear historical information.

Signed-off-by: Haozhong Zhang 
---
 xen/arch/x86/cpu/mcheck/mce.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
index 11d0e23..7618120 100644
--- a/xen/arch/x86/cpu/mcheck/mce.c
+++ b/xen/arch/x86/cpu/mcheck/mce.c
@@ -177,6 +177,7 @@ void mce_need_clearbank_register(mce_need_clearbank_t 
cbfunc)
 
 static struct mce_softirq_barrier mce_inside_bar, mce_severity_bar;
 static struct mce_softirq_barrier mce_trap_bar;
+static struct mce_softirq_barrier mce_handler_init_bar;
 
 /*
  * mce_logout_lock should only be used in the trap handler,
@@ -187,8 +188,6 @@ static struct mce_softirq_barrier mce_trap_bar;
 static DEFINE_SPINLOCK(mce_logout_lock);
 
 static atomic_t severity_cpu = ATOMIC_INIT(-1);
-static atomic_t found_error = ATOMIC_INIT(0);
-static cpumask_t mce_fatal_cpus;
 
 const struct mca_error_handler *__read_mostly mce_dhandlers;
 const struct mca_error_handler *__read_mostly mce_uhandlers;
@@ -453,12 +452,19 @@ static int mce_urgent_action(const struct cpu_user_regs 
*regs,
 /* Shared #MC handler. */
 void mcheck_cmn_handler(const struct cpu_user_regs *regs)
 {
+static atomic_t found_error;
+static cpumask_t mce_fatal_cpus;
 struct mca_banks *bankmask = mca_allbanks;
 struct mca_banks *clear_bank = __get_cpu_var(mce_clear_banks);
 uint64_t gstatus;
 mctelem_cookie_t mctc = NULL;
 struct mca_summary bs;
 
+mce_barrier_enter(_handler_init_bar);
+atomic_set(_error, 0);
+cpumask_clear(_fatal_cpus);
+mce_barrier_exit(_handler_init_bar);
+
 mce_spin_lock(_logout_lock);
 
 if (clear_bank != NULL) {
@@ -1767,6 +1773,7 @@ void mce_handler_init(void)
 mce_barrier_init(_inside_bar);
 mce_barrier_init(_severity_bar);
 mce_barrier_init(_trap_bar);
+mce_barrier_init(_handler_init_bar);
 spin_lock_init(_logout_lock);
 open_softirq(MACHINE_CHECK_SOFTIRQ, mce_softirq);
 }
-- 
2.10.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v4 00/19] Provide a command line option to choose how to handle SErrors

2017-04-05 Thread Wei Chen
Thanks to you and Julien :)

On 2017/4/6 3:18, Stefano Stabellini wrote:
> Thank you Wei. I committed this series. I fixed on commit patch #16 that
> has 2 asserts.
> 
> On Wed, 5 Apr 2017, Wei Chen wrote:
>>  From XSA-201, we know that, a guest could trigger SErrors when accessing
>> memory mapped HW in a non-conventional way. In the patches for XSA-201,
>> we crash the guest when we captured such asynchronous aborts to avoid data
>> corruption.
>>
>> In order to distinguish guest-generated SErrors from hypervisor-generated
>> SErrors. We have to place SError checking code in every EL1 -> EL2 paths.
>> That will be an overhead on entries caused by dsb/isb.
>>
>> But not all platforms want to categorize the SErrors. For example, a host
>> that is running with trusted guests. The administrator can confirm that
>> all guests that are running on the host will not trigger such SErrors. In
>> this user scene, we should provide some options to administrator to avoid
>> categorizing the SErrors. And then reduce the overhead of dsb/isb.
>>
>> We provided following 3 options to administrator to determine how to handle
>> the SErrors:
>>
>> * `diverse`:
>>The hypervisor will distinguish guest SErrors from hypervisor SErrors.
>>The guest generated SErrors will be forwarded to guests, the hypervisor
>>generated SErrors will cause the whole system crash.
>>It requires:
>>1. Place dsb/isb on all EL1 -> EL2 trap entries to categorize SErrors
>>   correctly.
>>2. Place dsb/isb on EL2 -> EL1 return paths to prevent slipping hypervisor
>>   SErrors to guests.
>>3. Place dsb/isb in context switch to isolate the SErrors between 2 vCPUs.
>>
>> * `forward`:
>>The hypervisor will not distinguish guest SErrors from hypervisor SErrors.
>>All SErrors will be forwarded to guests, except the SErrors generated when
>>idle vCPU is running. The idle domain doesn't have the ability to hanle 
>> the
>>SErrors, so we have to crash the whole system when we get SErros with idle
>>vCPU. This option will avoid most overhead of the dsb/isb, except the 
>> dsb/isb
>>in context switch which is used to isolate the SErrors between 2 vCPUs.
>>
>> * `panic`:
>>The hypervisor will not distinguish guest SErrors from hypervisor SErrors.
>>All SErrors will crash the whole system. This option will avoid all 
>> overhead
>>of the dsb/isb
>>
>> ---
>> v3->v4:
>> 1. Rename SKIP_CHECK_PENDING_VSERROR to SKIP_SYNCHRONIZE_SERROR_ENTRY_EXIT.
>> 2. Add ASSERT in SYNCHRONIZING_SERROR macro to ensure abort is enabled.
>> 3. Use one local_abort_is_enabled for ARM32 and ARM64.
>> 4. Fix some grammer issues.
>> 5. Add Reviewed-by tags from Julien and Stefano for most of this series.
>>
>> Wei Chen (19):
>>xen/arm: Save ESR_EL2 to avoid using mismatched value in syndrome
>>  check
>>xen/arm: Introduce a helper to get default HCR_EL2 flags
>>xen/arm: Set and restore HCR_EL2 register for each vCPU separately
>>xen/arm: Avoid setting/clearing HCR_RW at every context switch
>>xen/arm: Save HCR_EL2 when a guest took the SError
>>xen/arm: Introduce a virtual abort injection helper
>>xen/arm: Introduce a command line parameter for SErrors/Aborts
>>xen/arm: Introduce a initcall to update cpu_hwcaps by serror_op
>>xen/arm64: Use alternative to skip the check of pending serrors
>>xen/arm32: Use alternative to skip the check of pending serrors
>>xen/arm: Move macro VABORT_GEN_BY_GUEST to common header
>>xen/arm: Introduce new helpers to handle guest/hyp SErrors
>>xen/arm: Replace do_trap_guest_serror with new helpers
>>xen/arm: Unmask the Abort/SError bit in the exception entries
>>xen/arm: Introduce a helper to check local abort is enabled
>>xen/arm: Introduce a macro to synchronize SError
>>xen/arm: Isolate the SError between the context switch of 2 vCPUs
>>xen/arm: Prevent slipping hypervisor SError to guest
>>xen/arm: Handle guest external abort as guest SError
>>
>>   docs/misc/xen-command-line.markdown   |  44 
>>   xen/arch/arm/arm32/asm-offsets.c  |   1 +
>>   xen/arch/arm/arm32/entry.S|  28 -
>>   xen/arch/arm/arm32/traps.c|   5 +-
>>   xen/arch/arm/arm64/asm-offsets.c  |   1 +
>>   xen/arch/arm/arm64/domctl.c   |   6 ++
>>   xen/arch/arm/arm64/entry.S| 105 +--
>>   xen/arch/arm/arm64/traps.c|   2 +-
>>   xen/arch/arm/domain.c |  19 
>>   xen/arch/arm/domain_build.c   |   7 ++
>>   xen/arch/arm/p2m.c|  10 +-
>>   xen/arch/arm/traps.c  | 187 
>> +-
>>   xen/include/asm-arm/arm32/processor.h |  12 +--
>>   xen/include/asm-arm/arm64/processor.h |   3 +-
>>   xen/include/asm-arm/cpufeature.h  |   4 +-
>>   xen/include/asm-arm/domain.h  |   4 +
>>   xen/include/asm-arm/processor.h   |  30 +-
>>   

Re: [Xen-devel] [PATCH v3 1/9] x86/mce: handle LMCE locally

2017-04-05 Thread Haozhong Zhang
On 03/31/17 01:24 -0600, Jan Beulich wrote:
> >>> On 31.03.17 at 04:34,  wrote:
> > On 03/30/17 08:35 -0600, Jan Beulich wrote:
> >> >>> On 30.03.17 at 08:19,  wrote:
> >> > --- a/xen/arch/x86/cpu/mcheck/mce.c
> >> > +++ b/xen/arch/x86/cpu/mcheck/mce.c
> >> > @@ -42,6 +42,13 @@ DEFINE_PER_CPU_READ_MOSTLY(struct mca_banks *, 
> >> > poll_bankmask);
> >> >  DEFINE_PER_CPU_READ_MOSTLY(struct mca_banks *, no_cmci_banks);
> >> >  DEFINE_PER_CPU_READ_MOSTLY(struct mca_banks *, mce_clear_banks);
> >> >  
> >> > +/*
> >> > + * Flag to indicate that at least one non-local MCE on this CPU has
> >> > + * not been completed handled. It's set by mcheck_cmn_handler() and
> >> > + * cleared by mce_softirq().
> >> > + */
> >> > +static DEFINE_PER_CPU(bool, nonlocal_mce_in_progress);
> >> 
> >> Does a boolean really suffice here? I.e. can't there be a 2nd one
> >> while the first one is still being dealt with?
> > 
> > It's to indicate the existence of a non-local MCE, and mce_softirq()
> > will call mctelem_process_deferred() to handle all MCE's if it's true,
> > so a boolean flag is suffice.
> 
> I don't buy this, I'm sorry. What if a 2nd #MC occurs at the
> instruction boundary of setting the variable to false (in
> mce_softirq())? A subsequent mce_softirq() would then see
> the variable being false, wouldn't it?
> 

You are right. I missed the point that MC# can happen during
mce_softirq() and this patch 1 is problematic in that case. Let me
rethink about this.

Thanks,
Haozhong

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] Outreachy project - Xen Code Review Dashboard

2017-04-05 Thread Heather Booker
Hi!

I'd love to work on the Code Review Dashboard project for this round of
Outreachy.

Are the steps outlined here http://markmail.org/message/7adkmords3imkswd
still the first
contribution you'd like to see?

So is this a project that has been worked on in previous rounds of
GSOC/Outreachy also?
If so is there a place to find links to the previous participants blogs? :)

Should questions about how the specifications/completion of the microtask
be addressed to
IRC or this list? If IRC, which channel - #xen-opw or #metrics-grimoire? On
that note, I'm
curious why #metrics-grimoire is the listed channel on the project page -
are main contributors
involved in both projects? Or is it just because the Xen dashboard doesn't
have a channel?

Thanks!

Heather
___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [xen-4.5-testing baseline-only test] 71152: tolerable FAIL

2017-04-05 Thread Platform Team regression test user
This run is configured for baseline tests only.

flight 71152 xen-4.5-testing real [real]
http://osstest.xs.citrite.net/~osstest/testlogs/logs/71152/

Failures :-/ but no regressions.

Regressions which are regarded as allowable (not blocking):
 test-xtf-amd64-amd64-2   20 xtf/test-hvm32-invlpg~shadow fail blocked in 71100
 test-xtf-amd64-amd64-2 33 xtf/test-hvm32pae-invlpg~shadow fail blocked in 71100
 test-xtf-amd64-amd64-2   44 xtf/test-hvm64-invlpg~shadow fail blocked in 71100
 test-armhf-armhf-libvirt13 saverestore-support-check fail blocked in 71100
 test-xtf-amd64-amd64-4   54 leak-check/check fail blocked in 71100
 test-xtf-amd64-amd64-3   54 leak-check/check fail blocked in 71100
 test-xtf-amd64-amd64-5   54 leak-check/check fail blocked in 71100
 test-armhf-armhf-libvirt15 guest-start/debian.repeat fail blocked in 71100
 test-xtf-amd64-amd64-2   54 leak-check/check fail blocked in 71100
 test-xtf-amd64-amd64-1   54 leak-check/check fail blocked in 71100
 test-amd64-amd64-xl-qemuu-win7-amd64 15 guest-localmigrate/x10 fail blocked in 
71100
 test-amd64-amd64-xl-qemut-win7-amd64 16 guest-stop   fail blocked in 71100
 test-armhf-armhf-xl-vhd   9 debian-di-installfail blocked in 71100
 test-amd64-amd64-xl-qemut-winxpsp3  9 windows-installfail blocked in 71100

Tests which did not succeed, but are not blocking:
 test-armhf-armhf-xl-multivcpu 12 migrate-support-checkfail  never pass
 test-armhf-armhf-xl-multivcpu 13 saverestore-support-checkfail  never pass
 test-armhf-armhf-xl-credit2  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-credit2  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-midway   12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-midway   13 saverestore-support-checkfail   never pass
 test-armhf-armhf-libvirt 12 migrate-support-checkfail   never pass
 test-xtf-amd64-amd64-4   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-xtf-amd64-amd64-3   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-xtf-amd64-amd64-5   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-amd64-amd64-libvirt 12 migrate-support-checkfail   never pass
 test-amd64-amd64-xl-pvh-amd  11 guest-start  fail   never pass
 test-armhf-armhf-xl-rtds 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-rtds 13 saverestore-support-checkfail   never pass
 test-amd64-amd64-xl-pvh-intel 11 guest-start  fail  never pass
 test-amd64-i386-libvirt  12 migrate-support-checkfail   never pass
 test-xtf-amd64-amd64-2   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-armhf-armhf-libvirt-raw 10 guest-start  fail   never pass
 test-xtf-amd64-amd64-1   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-amd64-amd64-libvirt-vhd 11 migrate-support-checkfail   never pass
 test-amd64-amd64-qemuu-nested-amd 16 debian-hvm-install/l1/l2  fail never pass
 test-amd64-i386-xl-qemuu-win7-amd64 16 guest-stop  fail never pass
 test-amd64-i386-xl-qemut-win7-amd64 16 guest-stop  fail never pass

version targeted for testing:
 xen  cde86fc9fd92041a5ad3d65082e45b9e6a2c7334
baseline version:
 xen  1678521a8a8fbc440054ec51befe68e344c6c9df

Last test of basis71100  2017-03-27 05:53:22 Z9 days
Testing same since71152  2017-04-05 18:18:18 Z0 days1 attempts


People who touched revisions under test:
  Jan Beulich 

jobs:
 build-amd64-xtf  pass
 build-amd64  pass
 build-armhf  pass
 build-i386   pass
 build-amd64-libvirt  pass
 build-armhf-libvirt  pass
 build-i386-libvirt   pass
 build-amd64-prev pass
 build-i386-prev  pass
 build-amd64-pvopspass
 build-armhf-pvopspass
 build-i386-pvops pass
 build-amd64-rumprun  pass
 build-i386-rumprun   pass
 test-xtf-amd64-amd64-1   fail
 test-xtf-amd64-amd64-2  

[Xen-devel] [xen-4.7-testing test] 107209: tolerable FAIL - PUSHED

2017-04-05 Thread osstest service owner
flight 107209 xen-4.7-testing real [real]
http://logs.test-lab.xenproject.org/osstest/logs/107209/

Failures :-/ but no regressions.

Tests which are failing intermittently (not blocking):
 test-amd64-amd64-pair 3 host-install/src_host(3) broken in 107185 pass in 
107209
 test-armhf-armhf-xl-credit2  3 host-install(3) broken in 107185 pass in 107209
 test-armhf-armhf-libvirt-raw  6 xen-boot   fail pass in 107185

Regressions which are regarded as allowable (not blocking):
 test-armhf-armhf-libvirt-raw 12 saverestore-support-check fail in 107185 like 
107021
 test-armhf-armhf-libvirt-xsm 13 saverestore-support-checkfail  like 107021
 test-armhf-armhf-libvirt 13 saverestore-support-checkfail  like 107021
 test-amd64-i386-xl-qemuu-win7-amd64 16 guest-stop fail like 107021
 test-amd64-i386-xl-qemut-win7-amd64 16 guest-stop fail like 107021
 test-amd64-amd64-xl-qemuu-win7-amd64 16 guest-stopfail like 107021
 test-amd64-amd64-xl-rtds  9 debian-install   fail  like 107021

Tests which did not succeed, but are not blocking:
 test-arm64-arm64-libvirt-xsm  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl   1 build-check(1)   blocked  n/a
 build-arm64-libvirt   1 build-check(1)   blocked  n/a
 test-arm64-arm64-libvirt-qcow2  1 build-check(1)   blocked  n/a
 test-arm64-arm64-libvirt  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-credit2   1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-rtds  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-multivcpu  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-xsm   1 build-check(1)   blocked  n/a
 test-armhf-armhf-libvirt-raw 11 migrate-support-check fail in 107185 never pass
 build-arm64   5 xen-buildfail   never pass
 build-arm64-xsm   5 xen-buildfail   never pass
 build-arm64-pvops 5 kernel-build fail   never pass
 test-amd64-amd64-xl-pvh-intel 11 guest-start  fail  never pass
 test-amd64-amd64-xl-pvh-amd  11 guest-start  fail   never pass
 test-amd64-amd64-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-amd64-i386-libvirt  12 migrate-support-checkfail   never pass
 test-amd64-i386-libvirt-xsm  12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt 12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-armhf-armhf-xl-multivcpu 12 migrate-support-checkfail  never pass
 test-armhf-armhf-xl-multivcpu 13 saverestore-support-checkfail  never pass
 test-armhf-armhf-xl-arndale  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-arndale  13 saverestore-support-checkfail   never pass
 test-amd64-amd64-qemuu-nested-amd 16 debian-hvm-install/l1/l2  fail never pass
 test-amd64-amd64-libvirt-vhd 11 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-xsm  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-xsm  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-credit2  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-credit2  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-libvirt 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-cubietruck 12 migrate-support-checkfail never pass
 test-armhf-armhf-xl-cubietruck 13 saverestore-support-checkfail never pass
 test-amd64-amd64-xl-qemut-win7-amd64 16 guest-stop fail never pass
 test-armhf-armhf-xl-rtds 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-rtds 13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-vhd  11 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-vhd  12 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl  13 saverestore-support-checkfail   never pass

version targeted for testing:
 xen  ada9e109d7539ec93e1b554805721110d2807521
baseline version:
 xen  47ba140217118b2b5153f3529d548bc5bdc98ca5

Last test of basis   107021  2017-03-31 07:12:01 Z5 days
Testing same since   107185  2017-04-04 13:12:45 Z1 days2 attempts


People who touched revisions under test:
  George Dunlap 
  Jan Beulich 
  Juergen Gross 

jobs:
 

[Xen-devel] [xen-4.6-testing test] 107208: tolerable FAIL - PUSHED

2017-04-05 Thread osstest service owner
flight 107208 xen-4.6-testing real [real]
http://logs.test-lab.xenproject.org/osstest/logs/107208/

Failures :-/ but no regressions.

Tests which are failing intermittently (not blocking):
 test-amd64-i386-freebsd10-amd64 3 host-install(3) broken in 107186 pass in 
107208
 test-xtf-amd64-amd64-5 20 xtf/test-hvm32-invlpg~shadow fail in 107186 pass in 
107208
 test-xtf-amd64-amd64-5 33 xtf/test-hvm32pae-invlpg~shadow fail in 107186 pass 
in 107208
 test-xtf-amd64-amd64-5 44 xtf/test-hvm64-invlpg~shadow fail in 107186 pass in 
107208
 test-armhf-armhf-xl-arndale   6 xen-boot fail in 107186 pass in 107208
 test-armhf-armhf-xl-multivcpu  6 xen-boot  fail pass in 107186
 test-amd64-i386-xl-qemut-stubdom-debianhvm-amd64-xsm 15 guest-localmigrate/x10 
fail pass in 107186
 test-armhf-armhf-xl-rtds 15 guest-start/debian.repeat  fail pass in 107186

Regressions which are regarded as allowable (not blocking):
 test-armhf-armhf-libvirt 13 saverestore-support-checkfail  like 107151
 test-armhf-armhf-libvirt-xsm 13 saverestore-support-checkfail  like 107151
 test-amd64-i386-xl-qemuu-win7-amd64 16 guest-stop fail like 107151
 test-amd64-i386-xl-qemut-win7-amd64 16 guest-stop fail like 107151
 test-amd64-amd64-xl-qemut-win7-amd64 16 guest-stopfail like 107151
 test-amd64-amd64-xl-qemuu-win7-amd64 16 guest-stopfail like 107151
 test-armhf-armhf-libvirt-raw 12 saverestore-support-checkfail  like 107151

Tests which did not succeed, but are not blocking:
 test-armhf-armhf-xl-multivcpu 12 migrate-support-check fail in 107186 never 
pass
 test-armhf-armhf-xl-multivcpu 13 saverestore-support-check fail in 107186 
never pass
 test-xtf-amd64-amd64-3   64 xtf/test-pv32pae-xsa-194 fail   never pass
 test-xtf-amd64-amd64-4   64 xtf/test-pv32pae-xsa-194 fail   never pass
 test-xtf-amd64-amd64-1   64 xtf/test-pv32pae-xsa-194 fail   never pass
 test-amd64-amd64-xl-pvh-intel 11 guest-start  fail  never pass
 test-amd64-i386-libvirt  12 migrate-support-checkfail   never pass
 test-xtf-amd64-amd64-5   64 xtf/test-pv32pae-xsa-194 fail   never pass
 test-amd64-i386-libvirt-xsm  12 migrate-support-checkfail   never pass
 test-amd64-amd64-xl-pvh-amd  11 guest-start  fail   never pass
 test-amd64-amd64-libvirt 12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-armhf-armhf-libvirt 12 migrate-support-checkfail   never pass
 test-amd64-amd64-qemuu-nested-amd 16 debian-hvm-install/l1/l2  fail never pass
 test-amd64-amd64-libvirt-vhd 11 migrate-support-checkfail   never pass
 test-armhf-armhf-xl  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-cubietruck 12 migrate-support-checkfail never pass
 test-armhf-armhf-xl-cubietruck 13 saverestore-support-checkfail never pass
 test-armhf-armhf-xl-xsm  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-xsm  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-credit2  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-credit2  13 saverestore-support-checkfail   never pass
 test-xtf-amd64-amd64-2   64 xtf/test-pv32pae-xsa-194 fail   never pass
 test-armhf-armhf-libvirt-raw 11 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-rtds 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-rtds 13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-vhd  11 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-vhd  12 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-arndale  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-arndale  13 saverestore-support-checkfail   never pass

version targeted for testing:
 xen  bb92bb77bc98d44cc8e4d8e6d61ae82517455f41
baseline version:
 xen  f96efeb0c6b4f499194571ef6d767534ba851c6a

Last test of basis   107151  2017-04-03 09:51:21 Z2 days
Testing same since   107186  2017-04-04 13:12:45 Z1 days2 attempts


People who touched revisions under test:
  George Dunlap 
  Jan Beulich 
  Juergen Gross 

jobs:
 build-amd64-xsm  pass
 build-armhf-xsm  pass
 build-i386-xsm 

Re: [Xen-devel] [PATCH v5 30/30] ARM: vGIC: advertise LPI support

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> To let a guest know about the availability of virtual LPIs, set the
> respective bits in the virtual GIC registers and let a guest control
> the LPI enable bit.
> Only report the LPI capability if the host has initialized at least
> one ITS.
> This removes a "TBD" comment, as we now populate the processor number
> in the GICR_TYPE register.
> Advertise 24 bits worth of LPIs to the guest.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3.c | 46 +-
>  1 file changed, 41 insertions(+), 5 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
> index 3b01247..ba0e79f 100644
> --- a/xen/arch/arm/vgic-v3.c
> +++ b/xen/arch/arm/vgic-v3.c
> @@ -168,8 +168,12 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
> mmio_info_t *info,
>  switch ( gicr_reg )
>  {
>  case VREG32(GICR_CTLR):
> -/* We have not implemented LPI's, read zero */
> -goto read_as_zero_32;
> +if ( dabt.size != DABT_WORD ) goto bad_width;
> +spin_lock(>arch.vgic.lock);
> +*r = vgic_reg32_extract(!!(v->arch.vgic.flags & 
> VGIC_V3_LPIS_ENABLED),
> +info);
> +spin_unlock(>arch.vgic.lock);
> +return 1;
>  
>  case VREG32(GICR_IIDR):
>  if ( dabt.size != DABT_WORD ) goto bad_width;
> @@ -181,16 +185,20 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu 
> *v, mmio_info_t *info,
>  uint64_t typer, aff;
>  
>  if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
> -/* TBD: Update processor id in [23:8] when ITS support is added */
>  aff = (MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 3) << 56 |
> MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 2) << 48 |
> MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 1) << 40 |
> MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 0) << 32);
>  typer = aff;
> +/* We use the VCPU ID as the redistributor ID in bits[23:8] */
> +typer |= (v->vcpu_id & 0x) << 8;
>  
>  if ( v->arch.vgic.flags & VGIC_V3_RDIST_LAST )
>  typer |= GICR_TYPER_LAST;
>  
> +if ( v->domain->arch.vgic.has_its )
> +typer |= GICR_TYPER_PLPIS;
> +
>  *r = vgic_reg64_extract(typer, info);
>  
>  return 1;
> @@ -411,6 +419,17 @@ static uint64_t sanitize_pendbaser(uint64_t reg)
>  return reg;
>  }
>  
> +static void vgic_vcpu_enable_lpis(struct vcpu *v)
> +{
> +uint64_t reg = v->domain->arch.vgic.rdist_propbase;
> +unsigned int nr_lpis = BIT((reg & 0x1f) + 1) - LPI_OFFSET;
> +
> +if ( !v->domain->arch.vgic.nr_lpis )
> +v->domain->arch.vgic.nr_lpis = nr_lpis;

What if nr_lpis was already set and the nr_lpis has changed?


> +v->arch.vgic.flags |= VGIC_V3_LPIS_ENABLED;
> +}
> +
>  static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info,
>uint32_t gicr_reg,
>register_t r)
> @@ -421,8 +440,20 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu 
> *v, mmio_info_t *info,
>  switch ( gicr_reg )
>  {
>  case VREG32(GICR_CTLR):
> -/* LPI's not implemented */
> -goto write_ignore_32;
> +if ( dabt.size != DABT_WORD ) goto bad_width;
> +if ( !v->domain->arch.vgic.has_its )
> +return 1;
> +
> +spin_lock(>arch.vgic.lock);
> +
> +/* LPIs can only be enabled once, but never disabled again. */
> +if ( (r & GICR_CTLR_ENABLE_LPIS) &&
> + !(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED) )
> +vgic_vcpu_enable_lpis(v);
> +
> +spin_unlock(>arch.vgic.lock);
> +
> +return 1;
>  
>  case VREG32(GICR_IIDR):
>  /* RO */
> @@ -1032,6 +1063,11 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, 
> mmio_info_t *info,
>  typer = ((ncpus - 1) << GICD_TYPE_CPUS_SHIFT |
>   DIV_ROUND_UP(v->domain->arch.vgic.nr_spis, 32));
>  
> +if ( v->domain->arch.vgic.has_its )
> +{
> +typer |= GICD_TYPE_LPIS;
> +irq_bits = 24;
> +}
>  typer |= (irq_bits - 1) << GICD_TYPE_ID_BITS_SHIFT;
>  
>  *r = vgic_reg32_extract(typer, info);
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 26/30] ARM: vITS: handle INV command

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The INV command instructs the ITS to update the configuration data for
> a given LPI by re-reading its entry from the property table.
> We don't need to care so much about the priority value, but enabling
> or disabling an LPI has some effect: We remove or push virtual LPIs
> to their VCPUs, also check the virtual pending bit if an LPI gets enabled.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3-its.c | 96 
> ++
>  1 file changed, 96 insertions(+)
> 
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index 47f2884..0d4b20d 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -376,6 +376,99 @@ static int its_handle_int(struct virt_its *its, uint64_t 
> *cmdptr)
>  return 0;
>  }
>  
> +/*
> + * For a given virtual LPI read the enabled bit and priority from the virtual
> + * property table and update the virtual IRQ's state in the given 
> pending_irq.
> + */
> +static int update_lpi_property(struct domain *d, uint32_t vlpi,
> +   struct pending_irq *p)
> +{
> +paddr_t addr;
> +uint8_t property;
> +int ret;
> +
> +addr = d->arch.vgic.rdist_propbase & GENMASK_ULL(51, 12);
> +
> +ret = vgic_access_guest_memory(d, addr + vlpi - LPI_OFFSET,
> +   , sizeof(property), false);
> +if ( ret )
> +return ret;
> +
> +p->lpi_priority = property & LPI_PROP_PRIO_MASK;
> +if ( property & LPI_PROP_ENABLED )
> +set_bit(GIC_IRQ_GUEST_ENABLED, >status);
> +else
> +clear_bit(GIC_IRQ_GUEST_ENABLED, >status);
> +
> +return 0;
> +}
> +
> +/*
> + * For a given virtual LPI read the enabled bit and priority from the virtual
> + * property table and update the virtual IRQ's state.
> + * This takes care of removing or pushing of virtual LPIs to their VCPUs.
> + * Also check if this LPI is due to be injected and do it, if needed.
> + */
> +static int update_lpi_enabled_status(struct domain *d,
> + struct vcpu *vcpu, uint32_t vlpi)
> +{
> +struct pending_irq *p = d->arch.vgic.handler->lpi_to_pending(d, vlpi);
> +unsigned long flags;
> +int ret;
> +
> +if ( !p )
> +return -EINVAL;
> +
> +spin_lock_irqsave(>arch.vgic.lock, flags);
> +ret = update_lpi_property(d, vlpi, p);
> +if ( ret ) {
> +spin_unlock_irqrestore(>arch.vgic.lock, flags);
> +return ret;
> +}
> +
> +if ( test_bit(GIC_IRQ_GUEST_ENABLED, >status) )
> +{
> +if ( !list_empty(>inflight) &&
> + !test_bit(GIC_IRQ_GUEST_VISIBLE, >status) )
> +gic_raise_guest_irq(vcpu, vlpi, p->lpi_priority);
> +spin_unlock_irqrestore(>arch.vgic.lock, flags);

Something like this should work for LPIs too.



> +/* Check whether the LPI has fired while the guest had it disabled. 
> */
> +if ( test_and_clear_bit(GIC_IRQ_GUEST_LPI_PENDING, >status) )
> +vgic_vcpu_inject_irq(vcpu, vlpi);
> +}
> +else
> +{
> +clear_bit(GIC_IRQ_GUEST_ENABLED, >status);
> +spin_unlock_irqrestore(>arch.vgic.lock, flags);
> +
> +gic_remove_from_queues(vcpu, vlpi);
> +}
> +
> +return 0;
> +}
> +
> +static int its_handle_inv(struct virt_its *its, uint64_t *cmdptr)
> +{
> +uint32_t devid = its_cmd_get_deviceid(cmdptr);
> +uint32_t eventid = its_cmd_get_id(cmdptr);
> +struct vcpu *vcpu;
> +uint32_t vlpi;
> +
> +/* Translate the event into a vCPU/vLPI pair. */
> +if ( !read_itte(its, devid, eventid, , ) )
> +return -1;
> +
> +/*
> + * Now read the property table and update our cached status. This
> + * also takes care if this LPI now needs to be injected or removed.
> + */
> +if ( update_lpi_enabled_status(its->d, vcpu, vlpi) )
> +return -1;
> +
> +return 0;
> +}
> +
>  static int its_handle_mapc(struct virt_its *its, uint64_t *cmdptr)
>  {
>  uint32_t collid = its_cmd_get_collection(cmdptr);
> @@ -615,6 +708,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
> virt_its *its)
>  case GITS_CMD_INT:
>  ret = its_handle_int(its, command);
>  break;
> +case GITS_CMD_INV:
> +ret = its_handle_inv(its, command);
> +break;
>  case GITS_CMD_MAPC:
>  ret = its_handle_mapc(its, command);
>  break;
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 25/30] ARM: vITS: handle DISCARD command

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The DISCARD command drops the connection between a DeviceID/EventID
> and an LPI/collection pair.
> We mark the respective structure entries as not allocated and make
> sure that any queued IRQs are removed.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3-its.c | 32 
>  1 file changed, 32 insertions(+)
> 
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index 6afb915..47f2884 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -549,6 +549,35 @@ out_unlock:
>  return ret;
>  }
>  
> +static int its_handle_discard(struct virt_its *its, uint64_t *cmdptr)
> +{
> +uint32_t devid = its_cmd_get_deviceid(cmdptr);
> +uint32_t eventid = its_cmd_get_id(cmdptr);
> +struct pending_irq *pirq;
> +struct vcpu *vcpu;
> +uint32_t vlpi;
> +
> +if ( !read_itte(its, devid, eventid, , ) )
> +return -1;
> +
> +pirq = its->d->arch.vgic.handler->lpi_to_pending(its->d, vlpi);
> +if ( pirq )
> +{
> +clear_bit(GIC_IRQ_GUEST_QUEUED, >status);
> +gic_remove_from_queues(vcpu, vlpi);

we need to remove it from inflight


> +}
> +
> +if ( !write_itte(its, devid, eventid, UNMAPPED_COLLECTION, INVALID_LPI,
> + NULL) )
> +return -1;
> +
> +if ( !gicv3_assign_guest_event(its->d, its->doorbell_address,
> +   devid, eventid, NULL, 0) )
> +return -1;
> +
> +return 0;
> +}
> +
>  #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
>  
>  /*
> @@ -580,6 +609,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
> virt_its *its)
>  case GITS_CMD_CLEAR:
>  ret = its_handle_clear(its, command);
>  break;
> +case GITS_CMD_DISCARD:
> +ret = its_handle_discard(its, command);
> +break;
>  case GITS_CMD_INT:
>  ret = its_handle_int(its, command);
>  break;
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 24/30] ARM: vITS: handle MOVI command

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The MOVI command moves the interrupt affinity from one redistributor
> (read: VCPU) to another.
> For now migration of "live" LPIs is not yet implemented, but we store
> the changed affinity in the host LPI structure and in our virtual ITTE.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/gic-v3-its.c| 24 
>  xen/arch/arm/gic-v3-lpi.c| 15 +
>  xen/arch/arm/vgic-v3-its.c   | 47 
> 
>  xen/include/asm-arm/gic_v3_its.h |  4 
>  4 files changed, 90 insertions(+)
> 
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index d970119..a57e63a 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -851,6 +851,30 @@ struct pending_irq *gicv3_assign_guest_event(struct 
> domain *d,
>  return pirq;
>  }
>  
> +/* Changes the target VCPU for a given host LPI assigned to a domain. */
> +int gicv3_lpi_change_vcpu(struct domain *d, paddr_t vdoorbell,
> +  uint32_t vdevid, uint32_t veventid,
> +  unsigned int vcpu_id)
> +{
> +uint32_t host_lpi;
> +struct its_devices *dev;
> +
> +spin_lock(>arch.vgic.its_devices_lock);
> +dev = get_its_device(d, vdoorbell, vdevid);
> +if ( dev )
> +host_lpi = get_host_lpi(dev, veventid);
> +else
> +host_lpi = 0;
> +spin_unlock(>arch.vgic.its_devices_lock);
> +
> +if ( !host_lpi )
> +return -ENOENT;
> +
> +gicv3_lpi_update_host_vcpuid(host_lpi, vcpu_id);

we need to call vgic_migrate_irq


> +return 0;
> +}
> +
>  /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. 
> */
>  void gicv3_its_dt_init(const struct dt_device_node *node)
>  {
> diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
> index c997ed5..b9960aa 100644
> --- a/xen/arch/arm/gic-v3-lpi.c
> +++ b/xen/arch/arm/gic-v3-lpi.c
> @@ -234,6 +234,21 @@ void gicv3_lpi_update_host_entry(uint32_t host_lpi, int 
> domain_id,
>  write_u64_atomic(>data, hlpi.data);
>  }
>  
> +int gicv3_lpi_update_host_vcpuid(uint32_t host_lpi, unsigned int vcpu_id)
> +{
> +union host_lpi *hlpip;
> +
> +ASSERT(host_lpi >= LPI_OFFSET);
> +
> +host_lpi -= LPI_OFFSET;
> +
> +hlpip = _data.host_lpis[host_lpi / HOST_LPIS_PER_PAGE][host_lpi % 
> HOST_LPIS_PER_PAGE];
> +
> +write_u16_atomic(>vcpu_id, vcpu_id);
> +
> +return 0;
> +}
> +
>  static int gicv3_lpi_allocate_pendtable(uint64_t *reg)
>  {
>  uint64_t val;
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index 079dd44..6afb915 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -508,6 +508,47 @@ static int its_handle_mapti(struct virt_its *its, 
> uint64_t *cmdptr)
>  return 0;
>  }
>  
> +static int its_handle_movi(struct virt_its *its, uint64_t *cmdptr)
> +{
> +uint32_t devid = its_cmd_get_deviceid(cmdptr);
> +uint32_t eventid = its_cmd_get_id(cmdptr);
> +int collid = its_cmd_get_collection(cmdptr);
> +struct pending_irq *p;
> +struct vcpu *vcpu;
> +uint32_t vlpi;
> +int ret = -1;
> +
> +spin_lock(>its_lock);
> +/* Check for a mapped LPI and get the LPI number. */
> +if ( !read_itte_locked(its, devid, eventid, , ) )
> +goto out_unlock;
> +
> +/* Check the new collection ID and get the new VCPU pointer */
> +vcpu = get_vcpu_from_collection(its, collid);
> +if ( !vcpu )
> +goto out_unlock;
> +
> +/* Update our cached vcpu_id in the pending_irq. */
> +p = its->d->arch.vgic.handler->lpi_to_pending(its->d, vlpi);
> +p->vcpu_id = vcpu->vcpu_id;
> +
> +/* Now store the new collection in the translation table. */
> +if ( !write_itte_locked(its, devid, eventid, collid, vlpi, ) )
> +goto out_unlock;
> +
> +spin_unlock(>its_lock);
> +
> +/* TODO: lookup currently-in-guest virtual IRQs and migrate them? */
> +
> +return gicv3_lpi_change_vcpu(its->d, its->doorbell_address,
> + devid, eventid, vcpu->vcpu_id);
> +
> +out_unlock:
> +spin_unlock(>its_lock);
> +
> +return ret;
> +}
> +
>  #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
>  
>  /*
> @@ -552,6 +593,12 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
> virt_its *its)
>  case GITS_CMD_MAPTI:
>  ret = its_handle_mapti(its, command);
>  break;
> +case GITS_CMD_MOVALL:
> +gdprintk(XENLOG_G_INFO, "ITS: ignoring MOVALL command\n");
> +break;
> +case GITS_CMD_MOVI:
> +ret = its_handle_movi(its, command);
> +break;
>  case GITS_CMD_SYNC:
>  /* We handle ITS commands synchronously, so we ignore SYNC. */
>  break;
> diff --git a/xen/include/asm-arm/gic_v3_its.h 
> b/xen/include/asm-arm/gic_v3_its.h
> index 

Re: [Xen-devel] [PATCH v5 23/30] ARM: vITS: handle MAPTI command

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The MAPTI commands associates a DeviceID/EventID pair with a LPI/CPU
> pair and actually instantiates LPI interrupts.
> We connect the already allocated host LPI to this virtual LPI, so that
> any triggering LPI on the host can be quickly forwarded to a guest.
> Beside entering the VCPU and the virtual LPI number in the respective
> host LPI entry, we also initialize and add the already allocated
> struct pending_irq to our radix tree, so that we can now easily find it
> by its virtual LPI number.
> To be able to later find the targetting VCPU for any given LPI without
> having to walk *all* ITS tables, we store the VCPU ID in the pending_irq
> struct as well.
> This exports the vgic_init_pending_irq() function to be able to
> initialize a new struct pending_irq.
> As write_itte() is now eventually used, we can now add the static tag.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/gic-v3-its.c| 74 ++
>  xen/arch/arm/gic-v3-lpi.c| 18 ++
>  xen/arch/arm/vgic-v3-its.c   | 76 
> ++--
>  xen/arch/arm/vgic.c  |  2 +-
>  xen/include/asm-arm/gic_v3_its.h |  6 
>  xen/include/asm-arm/vgic.h   |  2 ++
>  6 files changed, 175 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index 76b0316..d970119 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -777,6 +777,80 @@ out:
>  return ret;
>  }
>  
> +/* Must be called with the its_device_lock held. */
> +static struct its_devices *get_its_device(struct domain *d, paddr_t 
> vdoorbell,
> +  uint32_t vdevid)
> +{
> +struct rb_node *node = d->arch.vgic.its_devices.rb_node;
> +struct its_devices *dev;
> +
> +ASSERT(spin_is_locked(>arch.vgic.its_devices_lock));
> +
> +while (node)
> +{
> +int cmp;
> +
> +dev = rb_entry(node, struct its_devices, rbnode);
> +cmp = compare_its_guest_devices(dev, vdoorbell, vdevid);
> +
> +if ( !cmp )
> +return dev;
> +
> +if ( cmp > 0 )
> +node = node->rb_left;
> +else
> +node = node->rb_right;
> +}
> +
> +return NULL;
> +}
> +
> +static uint32_t get_host_lpi(struct its_devices *dev, uint32_t eventid)
> +{
> +uint32_t host_lpi = 0;
> +
> +if ( dev && (eventid < dev->eventids) )
> +host_lpi = dev->host_lpi_blocks[eventid / LPI_BLOCK] +
> +   (eventid % LPI_BLOCK);
> +
> +return host_lpi;
> +}
> +
> +/*
> + * Connects the event ID for an already assigned device to the given 
> VCPU/vLPI
> + * pair. The corresponding physical LPI is already mapped on the host side
> + * (when assigning the physical device to the guest), so we just connect the
> + * target VCPU/vLPI pair to that interrupt to inject it properly if it fires.
> + * Returns a pointer to the already allocated struct pending_irq that is
> + * meant to be used by that event.
> + */
> +struct pending_irq *gicv3_assign_guest_event(struct domain *d,
> + paddr_t vdoorbell_address,
> + uint32_t vdevid, uint32_t 
> veventid,
> + struct vcpu *v, uint32_t 
> virt_lpi)
> +{
> +struct its_devices *dev;
> +struct pending_irq *pirq = NULL;
> +uint32_t host_lpi = 0;
> +
> +spin_lock(>arch.vgic.its_devices_lock);
> +dev = get_its_device(d, vdoorbell_address, vdevid);
> +if ( dev )
> +{
> +host_lpi = get_host_lpi(dev, veventid);
> +pirq = >pend_irqs[veventid];
> +}
> +spin_unlock(>arch.vgic.its_devices_lock);
> +
> +if ( !host_lpi || !pirq )
> +return NULL;
> +
> +gicv3_lpi_update_host_entry(host_lpi, d->domain_id,
> +v ? v->vcpu_id : INVALID_VCPU_ID, virt_lpi);
> +
> +return pirq;
> +}
> +
>  /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. 
> */
>  void gicv3_its_dt_init(const struct dt_device_node *node)
>  {
> diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
> index 7d20986..c997ed5 100644
> --- a/xen/arch/arm/gic-v3-lpi.c
> +++ b/xen/arch/arm/gic-v3-lpi.c
> @@ -216,6 +216,24 @@ void gicv3_do_LPI(unsigned int lpi)
>  rcu_unlock_domain(d);
>  }
>  
> +void gicv3_lpi_update_host_entry(uint32_t host_lpi, int domain_id,
> + unsigned int vcpu_id, uint32_t virt_lpi)
> +{
> +union host_lpi *hlpip, hlpi;
> +
> +ASSERT(host_lpi >= LPI_OFFSET);
> +
> +host_lpi -= LPI_OFFSET;
> +
> +hlpip = _data.host_lpis[host_lpi / HOST_LPIS_PER_PAGE][host_lpi % 
> HOST_LPIS_PER_PAGE];
> +
> +hlpi.virt_lpi = virt_lpi;
> +hlpi.dom_id = domain_id;
> +hlpi.vcpu_id = vcpu_id;
> +
> +

Re: [Xen-devel] [PATCH v5 22/30] ARM: vITS: handle MAPD command

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The MAPD command maps a device by associating a memory region for
> storing ITEs with a certain device ID.
> We store the given guest physical address in the device table, and, if
> this command comes from Dom0, tell the host ITS driver about this new
> mapping, so it can issue the corresponding host MAPD command and create
> the required tables.
> We simply use our existing guest memory access function to find the
> right ITT entry and store the mapping there.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3-its.c | 59 
> ++
>  1 file changed, 59 insertions(+)
> 
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index bbca5cf..0372ed0 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -42,6 +42,7 @@
>   */
>  struct virt_its {
>  struct domain *d;
> +paddr_t doorbell_address;
>  unsigned int devid_bits;
>  unsigned int intid_bits;
>  spinlock_t vcmd_lock;   /* Protects the virtual command buffer, 
> which */
> @@ -144,6 +145,20 @@ static struct vcpu *get_vcpu_from_collection(struct 
> virt_its *its,
>  #define DEV_TABLE_ENTRY(addr, bits) \
>  (((addr) & GENMASK_ULL(51, 8)) | (((bits) - 1) & GENMASK_ULL(7, 0)))
>  
> +/* Set the address of an ITT for a given device ID. */
> +static int its_set_itt_address(struct virt_its *its, uint32_t devid,
> +   paddr_t itt_address, uint32_t nr_bits)
> +{
> +paddr_t addr = get_baser_phys_addr(its->baser_dev);
> +uint64_t itt_entry = DEV_TABLE_ENTRY(itt_address, nr_bits);
> +
> +if ( devid >= its->max_devices )
> +return -ENOENT;
> +
> +return vgic_access_guest_memory(its->d, addr + devid * sizeof(uint64_t),
> +_entry, sizeof(itt_entry), true);
> +}
> +
>  /*
>   * Lookup the address of the Interrupt Translation Table associated with
>   * a device ID and return the address of the ITTE belonging to the event ID
> @@ -384,6 +399,47 @@ static int its_handle_mapc(struct virt_its *its, 
> uint64_t *cmdptr)
>  return 0;
>  }
>  
> +static int its_handle_mapd(struct virt_its *its, uint64_t *cmdptr)
> +{
> +/* size and devid get validated by the functions called below. */
> +uint32_t devid = its_cmd_get_deviceid(cmdptr);
> +unsigned int size = its_cmd_get_size(cmdptr) + 1;
> +bool valid = its_cmd_get_validbit(cmdptr);
> +paddr_t itt_addr = its_cmd_get_ittaddr(cmdptr);
> +int ret;

The size should be sanitized against the number of event support by the
vITS


> +/*
> + * There is no easy and clean way for Xen to know the ITS device ID of a
> + * particular (PCI) device, so we have to rely on the guest telling
> + * us about it. For *now* we are just using the device ID *Dom0* uses,
> + * because the driver there has the actual knowledge.
> + * Eventually this will be replaced with a dedicated hypercall to
> + * announce pass-through of devices.
> + */
> +if ( is_hardware_domain(its->d) )
> +{
> +/*
> + * Dom0's ITSes are mapped 1:1, so both addresses are the same.
> + * Also the device IDs are equal.
> + */
> +ret = gicv3_its_map_guest_device(its->d, its->doorbell_address, 
> devid,
> + its->doorbell_address, devid,
> + BIT(size), valid);
> +if ( ret )
> +return ret;
> +}
> +
> +spin_lock(>its_lock);
> +if ( valid )
> +ret = its_set_itt_address(its, devid, itt_addr, size);
> +else
> +ret = its_set_itt_address(its, devid, INVALID_PADDR, 1);
> +
> +spin_unlock(>its_lock);
> +
> +return ret;
> +}
> +
>  #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
>  
>  /*
> @@ -421,6 +477,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
> virt_its *its)
>  case GITS_CMD_MAPC:
>  ret = its_handle_mapc(its, command);
>  break;
> +case GITS_CMD_MAPD:
> +ret = its_handle_mapd(its, command);
> +break;
>  case GITS_CMD_SYNC:
>  /* We handle ITS commands synchronously, so we ignore SYNC. */
>  break;
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 19/30] ARM: vITS: handle CLEAR command

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> This introduces the ITS command handler for the CLEAR command, which
> clears the pending state of an LPI.
> This removes a not-yet injected, but already queued IRQ from a VCPU.
> As read_itte() is now eventually used, we add the static keyword.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3-its.c | 49 
> --
>  1 file changed, 47 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index a145666..71bc08a 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -191,8 +191,8 @@ static bool read_itte_locked(struct virt_its *its, 
> uint32_t devid,
>   * This function takes care of the locking by taking the its_lock itself, so
>   * a caller shall not hold this. Before returning, the lock is dropped again.
>   */
> -bool read_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
> -   struct vcpu **vcpu_ptr, uint32_t *vlpi_ptr)
> +static bool read_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
> +  struct vcpu **vcpu_ptr, uint32_t *vlpi_ptr)
>  {
>  bool ret;
>  
> @@ -277,6 +277,48 @@ static uint64_t its_cmd_mask_field(uint64_t *its_cmd, 
> unsigned int word,
>  #define its_cmd_get_validbit(cmd)   its_cmd_mask_field(cmd, 2, 63,  1)
>  #define its_cmd_get_ittaddr(cmd)(its_cmd_mask_field(cmd, 2, 8, 44) 
> << 8)
>  
> +/*
> + * CLEAR removes the pending state from an LPI. */
> +static int its_handle_clear(struct virt_its *its, uint64_t *cmdptr)
> +{
> +uint32_t devid = its_cmd_get_deviceid(cmdptr);
> +uint32_t eventid = its_cmd_get_id(cmdptr);
> +struct pending_irq *p;
> +struct vcpu *vcpu;
> +uint32_t vlpi;
> +unsigned long flags;
> +
> +/* Translate the DevID/EvID pair into a vCPU/vLPI pair. */
> +if ( !read_itte(its, devid, eventid, , ) )
> +return -1;
> +
> +p = its->d->arch.vgic.handler->lpi_to_pending(its->d, vlpi);
> +if ( !p )
> +return -1;
> +
> +spin_lock_irqsave(>arch.vgic.lock, flags);
> +
> +/* We store the pending bit for LPIs in our struct pending_irq. */
> +clear_bit(GIC_IRQ_GUEST_LPI_PENDING, >status);
> +
> +/*
> + * If the LPI is already visible on the guest, it is too late to
> + * clear the pending state. However this is a benign race that can
> + * happen on real hardware, too: If the LPI has already been forwarded
> + * to a CPU interface, a CLEAR request reaching the redistributor has
> + * no effect on that LPI anymore. Since LPIs are edge triggered and
> + * have no active state, we don't need to care about this here.
> + */
> +if ( !test_bit(GIC_IRQ_GUEST_VISIBLE, >status) )
> +{
> +/* Remove a pending, but not yet injected guest IRQ. */
> +clear_bit(GIC_IRQ_GUEST_QUEUED, >status);
> +gic_remove_from_queues(vcpu, vlpi);

I think you also need to remove it from >inflight

list_del_init(>inflight);


> +}
> +
> +return 0;
> +}
> +
>  #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
>  
>  /*
> @@ -305,6 +347,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
> virt_its *its)
>  
>  switch ( its_cmd_get_command(command) )
>  {
> +case GITS_CMD_CLEAR:
> +ret = its_handle_clear(its, command);
> +break;
>  case GITS_CMD_SYNC:
>  /* We handle ITS commands synchronously, so we ignore SYNC. */
>  break;
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 17/30] ARM: vITS: add command handling stub and MMIO emulation

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> Emulate the memory mapped ITS registers and provide a stub to introduce
> the ITS command handling framework (but without actually emulating any
> commands at this time).
>
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3-its.c| 416 
> ++
>  xen/arch/arm/vgic-v3.c|   9 -
>  xen/include/asm-arm/gic_v3_defs.h |   9 +
>  xen/include/asm-arm/gic_v3_its.h  |   3 +
>  4 files changed, 428 insertions(+), 9 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
> index 9dfda59..f6bf1ee 100644
> --- a/xen/arch/arm/vgic-v3-its.c
> +++ b/xen/arch/arm/vgic-v3-its.c
> @@ -78,6 +78,422 @@ void vgic_v3_its_free_domain(struct domain *d)
>  ASSERT(RB_EMPTY_ROOT(>arch.vgic.its_devices));
>  }
>  
> +/**
> + * Functions that handle ITS commands *
> + **/
> +
> +static uint64_t its_cmd_mask_field(uint64_t *its_cmd, unsigned int word,
> +   unsigned int shift, unsigned int size)
> +{
> +return (le64_to_cpu(its_cmd[word]) >> shift) & (BIT(size) - 1);
> +}
> +
> +#define its_cmd_get_command(cmd)its_cmd_mask_field(cmd, 0,  0,  8)
> +#define its_cmd_get_deviceid(cmd)   its_cmd_mask_field(cmd, 0, 32, 32)
> +#define its_cmd_get_size(cmd)   its_cmd_mask_field(cmd, 1,  0,  5)
> +#define its_cmd_get_id(cmd) its_cmd_mask_field(cmd, 1,  0, 32)
> +#define its_cmd_get_physical_id(cmd)its_cmd_mask_field(cmd, 1, 32, 32)
> +#define its_cmd_get_collection(cmd) its_cmd_mask_field(cmd, 2,  0, 16)
> +#define its_cmd_get_target_addr(cmd)its_cmd_mask_field(cmd, 2, 16, 32)
> +#define its_cmd_get_validbit(cmd)   its_cmd_mask_field(cmd, 2, 63,  1)
> +#define its_cmd_get_ittaddr(cmd)(its_cmd_mask_field(cmd, 2, 8, 44) 
> << 8)
> +
> +#define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
> +
> +/*
> + * Requires the vcmd_lock to be held.
> + * TODO: Investigate whether we can be smarter here and don't need to hold
> + * the lock all of the time.
> + */
> +static int vgic_its_handle_cmds(struct domain *d, struct virt_its *its)
> +{
> +paddr_t addr = its->cbaser & GENMASK_ULL(51, 12);
> +uint64_t command[4];
> +
> +ASSERT(spin_is_locked(>vcmd_lock));
> +
> +if ( its->cwriter >= ITS_CMD_BUFFER_SIZE(its->cbaser) )
> +return -1;
> +
> +while ( its->creadr != its->cwriter )
> +{
> +int ret;
> +
> +ret = vgic_access_guest_memory(d, addr + its->creadr,
> +   command, sizeof(command), false);
> +if ( ret )
> +return ret;
> +
> +switch ( its_cmd_get_command(command) )
> +{
> +case GITS_CMD_SYNC:
> +/* We handle ITS commands synchronously, so we ignore SYNC. */
> +break;
> +default:
> +gdprintk(XENLOG_WARNING, "ITS: unhandled ITS command %lu\n",
> + its_cmd_get_command(command));
> +break;
> +}
> +
> +its->creadr += ITS_CMD_SIZE;
> +if ( its->creadr == ITS_CMD_BUFFER_SIZE(its->cbaser) )
> +its->creadr = 0;
> +
> +if ( ret )
> +gdprintk(XENLOG_WARNING,
> + "ITS: ITS command error %d while handling command 
> %lu\n",
> + ret, its_cmd_get_command(command));
> +}
> +
> +return 0;
> +}
> +
> +/*
> + * ITS registers read access *
> + */
> +
> +static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
> + register_t *r, void *priv)
> +{
> +struct virt_its *its = priv;
> +uint64_t reg;
> +
> +switch ( info->gpa & 0x )
> +{
> +case VREG32(GITS_CTLR):
> +if ( info->dabt.size != DABT_WORD ) goto bad_width;
> +
> +spin_lock(>vcmd_lock);
> +spin_lock(>its_lock);
> +if ( its->enabled )
> +reg = GITS_CTLR_ENABLE;
> +else
> +reg = 0;
> +
> +if ( its->cwriter == its->creadr )
> +reg |= GITS_CTLR_QUIESCENT;
> +spin_unlock(>its_lock);
> +spin_unlock(>vcmd_lock);
> +
> +*r = vgic_reg32_extract(reg, info);
> +break;
> +case VREG32(GITS_IIDR):
> +if ( info->dabt.size != DABT_WORD ) goto bad_width;
> +*r = vgic_reg32_extract(GITS_IIDR_VALUE, info);
> +break;
> +case VREG64(GITS_TYPER):
> +if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width;
> +
> +reg = GITS_TYPER_PHYSICAL;
> +reg |= (sizeof(struct vits_itte) - 1) << GITS_TYPER_ITT_SIZE_SHIFT;
> +reg |= (its->intid_bits - 1) << GITS_TYPER_IDBITS_SHIFT;
> +reg |= (its->devid_bits - 1) << GITS_TYPER_DEVIDS_SHIFT;
> +*r = vgic_reg64_extract(reg, info);
> +break;

[Xen-devel] [linux-linus test] 107206: regressions - FAIL

2017-04-05 Thread osstest service owner
flight 107206 linux-linus real [real]
http://logs.test-lab.xenproject.org/osstest/logs/107206/

Regressions :-(

Tests which did not succeed and are blocking,
including tests which could not be run:
 test-armhf-armhf-xl-credit2  11 guest-start   fail REGR. vs. 59254
 test-armhf-armhf-xl-arndale  11 guest-start   fail REGR. vs. 59254
 test-armhf-armhf-xl-cubietruck 11 guest-start fail REGR. vs. 59254
 test-armhf-armhf-libvirt-xsm 11 guest-start   fail REGR. vs. 59254
 test-armhf-armhf-libvirt 11 guest-start   fail REGR. vs. 59254
 test-armhf-armhf-xl  11 guest-start   fail REGR. vs. 59254
 test-armhf-armhf-xl-xsm  11 guest-start   fail REGR. vs. 59254
 test-armhf-armhf-xl-multivcpu 11 guest-start  fail REGR. vs. 59254

Regressions which are regarded as allowable (not blocking):
 test-armhf-armhf-xl-rtds 11 guest-start   fail REGR. vs. 59254
 test-amd64-amd64-xl-rtds  9 debian-installfail REGR. vs. 59254
 test-armhf-armhf-xl-vhd   9 debian-di-install   fail baseline untested
 test-armhf-armhf-libvirt-raw  9 debian-di-install   fail baseline untested
 test-amd64-i386-xl-qemuu-win7-amd64 16 guest-stop  fail like 59254
 test-amd64-amd64-xl-qemut-win7-amd64 16 guest-stop fail like 59254
 test-amd64-i386-xl-qemut-win7-amd64 16 guest-stop  fail like 59254
 test-amd64-amd64-xl-qemuu-win7-amd64 16 guest-stop fail like 59254

Tests which did not succeed, but are not blocking:
 test-amd64-i386-libvirt-xsm  12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt 12 migrate-support-checkfail   never pass
 test-arm64-arm64-libvirt 11 guest-start  fail   never pass
 test-arm64-arm64-xl-xsm  11 guest-start  fail   never pass
 test-arm64-arm64-xl-multivcpu 11 guest-start  fail  never pass
 test-arm64-arm64-xl  11 guest-start  fail   never pass
 test-arm64-arm64-xl-credit2  11 guest-start  fail   never pass
 test-arm64-arm64-xl-rtds 11 guest-start  fail   never pass
 test-arm64-arm64-libvirt-xsm 11 guest-start  fail   never pass
 test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-amd64-amd64-libvirt-vhd 11 migrate-support-checkfail   never pass
 test-amd64-amd64-qemuu-nested-amd 16 debian-hvm-install/l1/l2  fail never pass
 test-amd64-i386-libvirt  12 migrate-support-checkfail   never pass
 test-arm64-arm64-libvirt-qcow2  9 debian-di-installfail never pass

version targeted for testing:
 linux308ac7563944787f8afc508568a3cda601c35a48
baseline version:
 linux45820c294fe1b1a9df495d57f40585ef2d069a39

Last test of basis59254  2015-07-09 04:20:48 Z  636 days
Failing since 59348  2015-07-10 04:24:05 Z  635 days  377 attempts
Testing same since   107206  2017-04-05 04:29:03 Z0 days1 attempts


8133 people touched revisions under test,
not listing them all

jobs:
 build-amd64-xsm  pass
 build-arm64-xsm  pass
 build-armhf-xsm  pass
 build-i386-xsm   pass
 build-amd64  pass
 build-arm64  pass
 build-armhf  pass
 build-i386   pass
 build-amd64-libvirt  pass
 build-arm64-libvirt  pass
 build-armhf-libvirt  pass
 build-i386-libvirt   pass
 build-amd64-pvopspass
 build-arm64-pvopspass
 build-armhf-pvopspass
 build-i386-pvops pass
 build-amd64-rumprun  pass
 build-i386-rumprun   pass
 test-amd64-amd64-xl  pass
 test-arm64-arm64-xl  fail
 test-armhf-armhf-xl  fail
 test-amd64-i386-xl   pass
 

Re: [Xen-devel] [PATCH v5 16/30] ARM: vGICv3: handle disabled LPIs

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> If a guest disables an LPI, we do not forward this to the associated
> host LPI to avoid queueing commands to the host ITS command queue.
> So it may happen that an LPI fires nevertheless on the host. In this
> case we can bail out early, but have to save the pending state on the
> virtual side. We do this by storing the pending bit in struct
> pending_irq, which is assiociated with mapped LPIs.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/gic-v3-lpi.c | 26 +-
>  1 file changed, 25 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
> index d8baebc..7d20986 100644
> --- a/xen/arch/arm/gic-v3-lpi.c
> +++ b/xen/arch/arm/gic-v3-lpi.c
> @@ -136,6 +136,22 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool 
> use_pta)
>  return per_cpu(lpi_redist, cpu).redist_id << 16;
>  }
>  
> +static bool vgic_can_inject_lpi(struct vcpu *vcpu, uint32_t vlpi)
> +{
> +struct pending_irq *p;
> +
> +p = vcpu->domain->arch.vgic.handler->lpi_to_pending(vcpu->domain, vlpi);
> +if ( !p )
> +return false;
> +
> +if ( test_bit(GIC_IRQ_GUEST_ENABLED, >status) )
> +return true;
> +
> +set_bit(GIC_IRQ_GUEST_LPI_PENDING, >status);

See alpine.DEB.2.10.1701051422020.2866@sstabellini-ThinkPad-X260


> +return false;
> +}
> +
>  /*
>   * Handle incoming LPIs, which are a bit special, because they are 
> potentially
>   * numerous and also only get injected into guests. Treat them specially 
> here,
> @@ -187,7 +203,15 @@ void gicv3_do_LPI(unsigned int lpi)
>  
>  /* Check if the VCPU is ready to receive LPIs. */
>  if ( vcpu->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
> -vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
> +{
> +/*
> + * We keep all host LPIs enabled, so check if it's disabled on the
> + * guest side and just record this LPI in the virtual pending table
> + * in this case. The guest picks it up once it gets enabled again.
> + */
> +if ( vgic_can_inject_lpi(vcpu, hlpi.virt_lpi) )
> +vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
> +}
>  
>  rcu_unlock_domain(d);
>  }
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 15/30] ARM: vGICv3: handle virtual LPI pending and property tables

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> Allow a guest to provide the address and size for the memory regions
> it has reserved for the GICv3 pending and property tables.
> We sanitise the various fields of the respective redistributor
> registers and map those pages into Xen's address space to have easy
> access.
> This introduces a function to read and write from and to guest memory,
> to be later able to access the tables located there.
> This vgic_access_guest_memory() function has been written by Vijaya Kumar
> as part of an earlier series.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3.c   | 152 
> ++-
>  xen/arch/arm/vgic.c  |  39 +++
>  xen/include/asm-arm/domain.h |   6 +-
>  xen/include/asm-arm/vgic.h   |   3 +
>  4 files changed, 182 insertions(+), 18 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
> index 2a14305..0623803 100644
> --- a/xen/arch/arm/vgic-v3.c
> +++ b/xen/arch/arm/vgic-v3.c
> @@ -19,12 +19,14 @@
>   */
>  
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -228,12 +230,21 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu 
> *v, mmio_info_t *info,
>  goto read_reserved;
>  
>  case VREG64(GICR_PROPBASER):
> -/* LPI's not implemented */
> -goto read_as_zero_64;
> +if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
> +
> +spin_lock(>arch.vgic.lock);
> +*r = vgic_reg64_extract(v->domain->arch.vgic.rdist_propbase, info);
> +spin_unlock(>arch.vgic.lock);
> +return 1;
>  
>  case VREG64(GICR_PENDBASER):
> -/* LPI's not implemented */
> -goto read_as_zero_64;
> +if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
> +
> +spin_lock(>arch.vgic.lock);
> +*r = vgic_reg64_extract(v->arch.vgic.rdist_pendbase, info);
> +*r &= ~GICR_PENDBASER_PTZ;   /* WO, reads as 0 */
> +spin_unlock(>arch.vgic.lock);
> +return 1;
>  
>  case 0x0080:
>  goto read_reserved;
> @@ -301,11 +312,6 @@ bad_width:
>  domain_crash_synchronous();
>  return 0;
>  
> -read_as_zero_64:
> -if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
> -*r = 0;
> -return 1;
> -
>  read_as_zero_32:
>  if ( dabt.size != DABT_WORD ) goto bad_width;
>  *r = 0;
> @@ -330,11 +336,95 @@ read_unknown:
>  return 1;
>  }
>  
> +static uint64_t vgic_sanitise_field(uint64_t reg, uint64_t field_mask,
> +int field_shift,
> +uint64_t (*sanitise_fn)(uint64_t))
> +{
> +uint64_t field = (reg & field_mask) >> field_shift;
> +
> +field = sanitise_fn(field) << field_shift;
> +
> +return (reg & ~field_mask) | field;
> +}
> +
> +/* We want to avoid outer shareable. */
> +static uint64_t vgic_sanitise_shareability(uint64_t field)
> +{
> +switch ( field )
> +{
> +case GIC_BASER_OuterShareable:
> +return GIC_BASER_InnerShareable;
> +default:
> +return field;
> +}
> +}
> +
> +/* Avoid any inner non-cacheable mapping. */
> +static uint64_t vgic_sanitise_inner_cacheability(uint64_t field)
> +{
> +switch ( field )
> +{
> +case GIC_BASER_CACHE_nCnB:
> +case GIC_BASER_CACHE_nC:
> +return GIC_BASER_CACHE_RaWb;
> +default:
> +return field;
> +}
> +}
> +
> +/* Non-cacheable or same-as-inner are OK. */
> +static uint64_t vgic_sanitise_outer_cacheability(uint64_t field)
> +{
> +switch ( field )
> +{
> +case GIC_BASER_CACHE_SameAsInner:
> +case GIC_BASER_CACHE_nC:
> +return field;
> +default:
> +return GIC_BASER_CACHE_nC;
> +}
> +}
> +
> +static uint64_t sanitize_propbaser(uint64_t reg)
> +{
> +reg = vgic_sanitise_field(reg, GICR_PROPBASER_SHAREABILITY_MASK,
> +  GICR_PROPBASER_SHAREABILITY_SHIFT,
> +  vgic_sanitise_shareability);
> +reg = vgic_sanitise_field(reg, GICR_PROPBASER_INNER_CACHEABILITY_MASK,
> +  GICR_PROPBASER_INNER_CACHEABILITY_SHIFT,
> +  vgic_sanitise_inner_cacheability);
> +reg = vgic_sanitise_field(reg, GICR_PROPBASER_OUTER_CACHEABILITY_MASK,
> +  GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT,
> +  vgic_sanitise_outer_cacheability);
> +
> +reg &= ~GICR_PROPBASER_RES0_MASK;
> +
> +return reg;
> +}
> +
> +static uint64_t sanitize_pendbaser(uint64_t reg)
> +{
> +reg = vgic_sanitise_field(reg, GICR_PENDBASER_SHAREABILITY_MASK,
> +  GICR_PENDBASER_SHAREABILITY_SHIFT,
> +  vgic_sanitise_shareability);
> +reg = vgic_sanitise_field(reg, GICR_PENDBASER_INNER_CACHEABILITY_MASK,
> +  

Re: [Xen-devel] [PATCH v5 13/30] ARM: GICv3: forward pending LPIs to guests

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> Upon receiving an LPI on the host, we need to find the right VCPU and
> virtual IRQ number to get this IRQ injected.
> Iterate our two-level LPI table to find this information quickly when
> the host takes an LPI. Call the existing injection function to let the
> GIC emulation deal with this interrupt.
> Also we enhance struct pending_irq to cache the pending bit and the
> priority information for LPIs, as we can't afford to walk the tables in
> guest memory every time we handle an incoming LPI.
> This introduces a do_LPI() as a hardware gic_ops and a function to
> retrieve the (cached) priority value of an LPI and a vgic_ops.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/gic-v2.c|  7 +
>  xen/arch/arm/gic-v3-lpi.c| 56 
> 
>  xen/arch/arm/gic-v3.c|  1 +
>  xen/arch/arm/gic.c   |  8 +-
>  xen/arch/arm/vgic-v2.c   |  7 +
>  xen/arch/arm/vgic-v3.c   | 12 +
>  xen/arch/arm/vgic.c  |  7 -
>  xen/include/asm-arm/gic.h|  2 ++
>  xen/include/asm-arm/gic_v3_its.h |  8 ++
>  xen/include/asm-arm/vgic.h   |  3 +++
>  10 files changed, 109 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
> index 270a136..f4d7949 100644
> --- a/xen/arch/arm/gic-v2.c
> +++ b/xen/arch/arm/gic-v2.c
> @@ -1217,6 +1217,12 @@ static int __init gicv2_init(void)
>  return 0;
>  }
>  
> +void gicv2_do_LPI(unsigned int lpi)
> +{
> +/* No LPIs in a GICv2 */
> +BUG();
> +}
> +
>  const static struct gic_hw_operations gicv2_ops = {
>  .info= _info,
>  .init= gicv2_init,
> @@ -1244,6 +1250,7 @@ const static struct gic_hw_operations gicv2_ops = {
>  .make_hwdom_madt = gicv2_make_hwdom_madt,
>  .map_hwdom_extra_mappings = gicv2_map_hwdown_extra_mappings,
>  .iomem_deny_access   = gicv2_iomem_deny_access,
> +.do_LPI  = gicv2_do_LPI,
>  };
>  
>  /* Set up the GIC */
> diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
> index 0785701..d8baebc 100644
> --- a/xen/arch/arm/gic-v3-lpi.c
> +++ b/xen/arch/arm/gic-v3-lpi.c
> @@ -136,6 +136,62 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool 
> use_pta)
>  return per_cpu(lpi_redist, cpu).redist_id << 16;
>  }
>  
> +/*
> + * Handle incoming LPIs, which are a bit special, because they are 
> potentially
> + * numerous and also only get injected into guests. Treat them specially 
> here,
> + * by just looking up their target vCPU and virtual LPI number and hand it
> + * over to the injection function.
> + * Please note that LPIs are edge-triggered only, also have no active state,
> + * so spurious interrupts on the host side are no issue (we can just ignore
> + * them).
> + * Also a guest cannot expect that firing interrupts that haven't been
> + * fully configured yet will reach the CPU, so we don't need to care about
> + * this special case.
> + */
> +void gicv3_do_LPI(unsigned int lpi)
> +{
> +struct domain *d;
> +union host_lpi *hlpip, hlpi;
> +struct vcpu *vcpu;
> +
> +/* EOI the LPI already. */
> +WRITE_SYSREG32(lpi, ICC_EOIR1_EL1);
> +
> +/* Find out if a guest mapped something to this physical LPI. */
> +hlpip = gic_get_host_lpi(lpi);
> +if ( !hlpip )
> +return;
> +
> +hlpi.data = read_u64_atomic(>data);
> +
> +/*
> + * Unmapped events are marked with an invalid LPI ID. We can safely
> + * ignore them, as they have no further state and no-one can expect
> + * to see them if they have not been mapped.
> + */
> +if ( hlpi.virt_lpi == INVALID_LPI )
> +return;
> +
> +d = rcu_lock_domain_by_id(hlpi.dom_id);
> +if ( !d )
> +return;
> +
> +/* Make sure we don't step beyond the vcpu array. */
> +if ( hlpi.vcpu_id >= d->max_vcpus )
> +{
> +rcu_unlock_domain(d);
> +return;
> +}
> +
> +vcpu = d->vcpu[hlpi.vcpu_id];
> +
> +/* Check if the VCPU is ready to receive LPIs. */
> +if ( vcpu->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
> +vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
> +
> +rcu_unlock_domain(d);
> +}
> +
>  static int gicv3_lpi_allocate_pendtable(uint64_t *reg)
>  {
>  uint64_t val;
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index a559e5e..63dbc21 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -1670,6 +1670,7 @@ static const struct gic_hw_operations gicv3_ops = {
>  .make_hwdom_dt_node  = gicv3_make_hwdom_dt_node,
>  .make_hwdom_madt = gicv3_make_hwdom_madt,
>  .iomem_deny_access   = gicv3_iomem_deny_access,
> +.do_LPI  = gicv3_do_LPI,
>  };
>  
>  static int __init gicv3_dt_preinit(struct dt_device_node *node, const void 
> *data)
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index 

Re: [Xen-devel] [PATCH v5 11/30] ARM: GICv3 ITS: introduce device mapping

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The ITS uses device IDs to map LPIs to a device. Dom0 will later use
> those IDs, which we directly pass on to the host.
> For this we have to map each device that Dom0 may request to a host
> ITS device with the same identifier.
> Allocate the respective memory and enter each device into an rbtree to
> later be able to iterate over it or to easily teardown guests.
> Because device IDs are per ITS, we need to identify a virtual ITS. We
> use the doorbell address for that purpose, as it is a nice architectural
> MSI property and spares us handling with opaque pointer or break
> the VGIC abstraction.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/gic-v3-its.c| 263 
> +++
>  xen/arch/arm/vgic-v3-its.c   |   3 +
>  xen/include/asm-arm/domain.h |   3 +
>  xen/include/asm-arm/gic_v3_its.h |  13 ++
>  4 files changed, 282 insertions(+)
> 
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index eb47c9d..45bbfa7 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -21,6 +21,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -36,6 +38,26 @@
>   */
>  LIST_HEAD(host_its_list);
>  
> +/*
> + * Describes a device which is using the ITS and is used by a guest.
> + * Since device IDs are per ITS (in contrast to vLPIs, which are per
> + * guest), we have to differentiate between different virtual ITSes.
> + * We use the doorbell address here, since this is a nice architectural
> + * property of MSIs in general and we can easily get to the base address
> + * of the ITS and look that up.
> + */
> +struct its_devices {
> +struct rb_node rbnode;
> +struct host_its *hw_its;
> +void *itt_addr;
> +paddr_t guest_doorbell; /* Identifies the virtual ITS */
> +uint32_t host_devid;
> +uint32_t guest_devid;
> +uint32_t eventids;  /* Number of event IDs (MSIs) */
> +uint32_t *host_lpi_blocks;  /* Which LPIs are used on the host */
> +struct pending_irq *pend_irqs;  /* One struct per event */
> +};
> +
>  bool gicv3_its_host_has_its(void)
>  {
>  return !list_empty(_its_list);
> @@ -185,6 +207,30 @@ static int its_send_cmd_mapc(struct host_its *its, 
> uint32_t collection_id,
>  return its_send_command(its, cmd);
>  }
>  
> +static int its_send_cmd_mapd(struct host_its *its, uint32_t deviceid,
> + uint8_t size_bits, paddr_t itt_addr, bool valid)
> +{
> +uint64_t cmd[4];
> +
> +if ( valid )
> +{
> +ASSERT(size_bits <= its->evid_bits);
> +ASSERT(size_bits > 0);
> +ASSERT(!(itt_addr & ~GENMASK_ULL(51, 8)));
> +
> +/* The number of events is encoded as "number of bits minus one". */
> +size_bits--;
> +}
> +cmd[0] = GITS_CMD_MAPD | ((uint64_t)deviceid << 32);
> +cmd[1] = size_bits;
> +cmd[2] = itt_addr;
> +if ( valid )
> +cmd[2] |= GITS_VALID_BIT;
> +cmd[3] = 0x00;
> +
> +return its_send_command(its, cmd);
> +}
> +
>  static int its_send_cmd_inv(struct host_its *its,
>  uint32_t deviceid, uint32_t eventid)
>  {
> @@ -477,6 +523,66 @@ int gicv3_its_init(void)
>  return 0;
>  }
>  
> +static int remove_mapped_guest_device(struct its_devices *dev)
> +{
> +int ret = 0;
> +unsigned int i;
> +
> +if ( dev->hw_its )
> +/* MAPD also discards all events with this device ID. */
> +ret = its_send_cmd_mapd(dev->hw_its, dev->host_devid, 0, 0, false);
> +
> +for ( i = 0; i < dev->eventids / LPI_BLOCK; i++ )
> +gicv3_free_host_lpi_block(dev->host_lpi_blocks[i]);
> +
> +/* Make sure the MAPD command above is really executed. */
> +if ( !ret )
> +ret = gicv3_its_wait_commands(dev->hw_its);
> +
> +/* This should never happen, but just in case ... */
> +if ( ret )
> +printk(XENLOG_WARNING "Can't unmap host ITS device 0x%x\n",
> +   dev->host_devid);
> +
> +xfree(dev->itt_addr);
> +xfree(dev->pend_irqs);
> +xfree(dev->host_lpi_blocks);
> +xfree(dev);
> +
> +return 0;
> +}
> +
> +static struct host_its *gicv3_its_find_by_doorbell(paddr_t doorbell_address)
> +{
> +struct host_its *hw_its;
> +
> +list_for_each_entry(hw_its, _its_list, entry)
> +{
> +if ( hw_its->addr + ITS_DOORBELL_OFFSET == doorbell_address )
> +return hw_its;
> +}
> +
> +return NULL;
> +}
> +
> +static int compare_its_guest_devices(struct its_devices *dev,
> + paddr_t vdoorbell, uint32_t vdevid)
> +{
> +if ( dev->guest_doorbell < vdoorbell )
> +return -1;
> +
> +if ( dev->guest_doorbell > vdoorbell )
> +return 1;
> +
> +if ( dev->guest_devid < vdevid )
> +return -1;
> +
> +if ( dev->guest_devid > vdevid )
> +  

Re: [Xen-devel] [PATCH v5 09/30] ARM: GICv3 ITS: introduce host LPI array

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The number of LPIs on a host can be potentially huge (millions),
> although in practise will be mostly reasonable. So prematurely allocating
> an array of struct irq_desc's for each LPI is not an option.
> However Xen itself does not care about LPIs, as every LPI will be injected
> into a guest (Dom0 for now).
> Create a dense data structure (8 Bytes) for each LPI which holds just
> enough information to determine the virtual IRQ number and the VCPU into
> which the LPI needs to be injected.
> Also to not artificially limit the number of LPIs, we create a 2-level
> table for holding those structures.
> This patch introduces functions to initialize these tables and to
> create, lookup and destroy entries for a given LPI.
> By using the naturally atomic access guarantee the native uint64_t data
> type gives us, we allocate and access LPI information in a way that does
> not require a lock.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/gic-v3-its.c|  60 +++
>  xen/arch/arm/gic-v3-lpi.c| 227 
> +++
>  xen/include/asm-arm/gic_v3_its.h |   6 ++
>  xen/include/asm-arm/irq.h|   8 ++
>  4 files changed, 301 insertions(+)
> 
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index 1ecd63b..eb47c9d 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -157,6 +157,20 @@ static int its_send_cmd_sync(struct host_its *its, 
> unsigned int cpu)
>  return its_send_command(its, cmd);
>  }
>  
> +static int its_send_cmd_mapti(struct host_its *its,
> +  uint32_t deviceid, uint32_t eventid,
> +  uint32_t pintid, uint16_t icid)
> +{
> +uint64_t cmd[4];
> +
> +cmd[0] = GITS_CMD_MAPTI | ((uint64_t)deviceid << 32);
> +cmd[1] = eventid | ((uint64_t)pintid << 32);
> +cmd[2] = icid;
> +cmd[3] = 0x00;
> +
> +return its_send_command(its, cmd);
> +}
> +
>  static int its_send_cmd_mapc(struct host_its *its, uint32_t collection_id,
>   unsigned int cpu)
>  {
> @@ -171,6 +185,19 @@ static int its_send_cmd_mapc(struct host_its *its, 
> uint32_t collection_id,
>  return its_send_command(its, cmd);
>  }
>  
> +static int its_send_cmd_inv(struct host_its *its,
> +uint32_t deviceid, uint32_t eventid)
> +{
> +uint64_t cmd[4];
> +
> +cmd[0] = GITS_CMD_INV | ((uint64_t)deviceid << 32);
> +cmd[1] = eventid;
> +cmd[2] = 0x00;
> +cmd[3] = 0x00;
> +
> +return its_send_command(its, cmd);
> +}
> +
>  /* Set up the (1:1) collection mapping for the given host CPU. */
>  int gicv3_its_setup_collection(unsigned int cpu)
>  {
> @@ -450,6 +477,39 @@ int gicv3_its_init(void)
>  return 0;
>  }
>  
> +/*
> + * On the host ITS @its, map @nr_events consecutive LPIs.
> + * The mapping connects a device @devid and event @eventid pair to LPI @lpi,
> + * increasing both @eventid and @lpi to cover the number of requested LPIs.
> + */
> +static int gicv3_its_map_host_events(struct host_its *its,
> + uint32_t devid, uint32_t eventid,
> + uint32_t lpi, uint32_t nr_events)
> +{
> +uint32_t i;
> +int ret;
> +
> +for ( i = 0; i < nr_events; i++ )
> +{
> +/* For now we map every host LPI to host CPU 0 */
> +ret = its_send_cmd_mapti(its, devid, eventid + i, lpi + i, 0);
> +if ( ret )
> +return ret;
> +
> +ret = its_send_cmd_inv(its, devid, eventid + i);
> +if ( ret )
> +return ret;
> +}
> +
> +/* TODO: Consider using INVALL here. Didn't work on the model, though. */
> +
> +ret = its_send_cmd_sync(its, 0);
> +if ( ret )
> +return ret;
> +
> +return gicv3_its_wait_commands(its);
> +}
> +
>  /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. 
> */
>  void gicv3_its_dt_init(const struct dt_device_node *node)
>  {
> diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
> index 9d3df7f..0785701 100644
> --- a/xen/arch/arm/gic-v3-lpi.c
> +++ b/xen/arch/arm/gic-v3-lpi.c
> @@ -20,14 +20,37 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
>  #include 
>  #include 
>  
> +/*
> + * There could be a lot of LPIs on the host side, and they always go to
> + * a guest. So having a struct irq_desc for each of them would be wasteful
> + * and useless.
> + * Instead just store enough information to find the right VCPU to inject
> + * those LPIs into, which just requires the virtual LPI number.
> + * To avoid a global lock on this data structure, this is using a lockless
> + * approach relying on the architectural atomicity of native data types:
> + * We read or write the "data" view of this union atomically, then can
> + * access the 

Re: [Xen-devel] [PATCH v5 08/30] ARM: GICv3 ITS: introduce ITS command handling

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> To be able to easily send commands to the ITS, create the respective
> wrapper functions, which take care of the ring buffer.
> The first two commands we implement provide methods to map a collection
> to a redistributor (aka host core) and to flush the command queue (SYNC).
> Start using these commands for mapping one collection to each host CPU.
> As an ITS might choose between *two* ways of addressing a redistributor,
> we store both the MMIO base address as well as the processor number in
> a per-CPU variable to give each ITS what it wants.
> 
> Signed-off-by: Andre Przywara 

Reviewed-by: Stefano Stabellini 


> ---
>  xen/arch/arm/gic-v3-its.c | 199 
> ++
>  xen/arch/arm/gic-v3-lpi.c |  28 ++
>  xen/arch/arm/gic-v3.c |  26 -
>  xen/include/asm-arm/gic_v3_defs.h |   2 +
>  xen/include/asm-arm/gic_v3_its.h  |  37 +++
>  5 files changed, 291 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index d8e978a..1ecd63b 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -19,11 +19,14 @@
>   */
>  
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define ITS_CMD_QUEUE_SZSZ_1M
>  
> @@ -38,6 +41,160 @@ bool gicv3_its_host_has_its(void)
>  return !list_empty(_its_list);
>  }
>  
> +#define BUFPTR_MASK GENMASK_ULL(19, 5)
> +static int its_send_command(struct host_its *hw_its, const void *its_cmd)
> +{
> +/*
> + * The command queue should actually never become full, if it does anyway
> + * and this situation is not resolved quickly, this points to a much
> + * bigger problem, probably an hardware error.
> + * So to cover the one-off case where we actually hit a full command
> + * queue, we introduce a small grace period to not give up too quickly.
> + * Given the usual multi-hundred MHz frequency the ITS usually runs with,
> + * one millisecond (for a single command) seem to be more than enough.
> + * But this value is rather arbitrarily chosen based on theoretical
> + * considerations.
> + */
> +s_time_t deadline = NOW() + MILLISECS(1);
> +uint64_t readp, writep;
> +int ret = -EBUSY;
> +
> +/* No ITS commands from an interrupt handler (at the moment). */
> +ASSERT(!in_irq());
> +
> +spin_lock(_its->cmd_lock);
> +
> +do {
> +readp = readq_relaxed(hw_its->its_base + GITS_CREADR) & BUFPTR_MASK;
> +writep = readq_relaxed(hw_its->its_base + GITS_CWRITER) & 
> BUFPTR_MASK;
> +
> +if ( ((writep + ITS_CMD_SIZE) % ITS_CMD_QUEUE_SZ) != readp )
> +{
> +ret = 0;
> +break;
> +}
> +
> +/*
> + * If the command queue is full, wait for a bit in the hope it drains
> + * before giving up.
> + */
> +spin_unlock(_its->cmd_lock);
> +cpu_relax();
> +udelay(1);
> +spin_lock(_its->cmd_lock);
> +} while ( NOW() <= deadline );
> +
> +if ( ret )
> +{
> +spin_unlock(_its->cmd_lock);
> +if ( printk_ratelimit() )
> +printk(XENLOG_WARNING "host ITS: command queue full.\n");
> +return ret;
> +}
> +
> +memcpy(hw_its->cmd_buf + writep, its_cmd, ITS_CMD_SIZE);
> +if ( hw_its->flags & HOST_ITS_FLUSH_CMD_QUEUE )
> +clean_and_invalidate_dcache_va_range(hw_its->cmd_buf + writep,
> + ITS_CMD_SIZE);
> +else
> +dsb(ishst);
> +
> +writep = (writep + ITS_CMD_SIZE) % ITS_CMD_QUEUE_SZ;
> +writeq_relaxed(writep & BUFPTR_MASK, hw_its->its_base + GITS_CWRITER);
> +
> +spin_unlock(_its->cmd_lock);
> +
> +return 0;
> +}
> +
> +/* Wait for an ITS to finish processing all commands. */
> +static int gicv3_its_wait_commands(struct host_its *hw_its)
> +{
> +/*
> + * As there could be quite a number of commands in a queue, we will
> + * wait a bit longer than the one millisecond for a single command above.
> + * Again this value is based on theoretical considerations, actually the
> + * command queue should drain much faster.
> + */
> +s_time_t deadline = NOW() + MILLISECS(100);
> +uint64_t readp, writep;
> +
> +do {
> +spin_lock(_its->cmd_lock);
> +readp = readq_relaxed(hw_its->its_base + GITS_CREADR) & BUFPTR_MASK;
> +writep = readq_relaxed(hw_its->its_base + GITS_CWRITER) & 
> BUFPTR_MASK;
> +spin_unlock(_its->cmd_lock);
> +
> +if ( readp == writep )
> +return 0;
> +
> +cpu_relax();
> +udelay(1);
> +} while ( NOW() <= deadline );
> +
> +return -ETIMEDOUT;
> +}
> +
> +static uint64_t encode_rdbase(struct host_its *hw_its, unsigned int cpu,
> + 

Re: [Xen-devel] [PATCH v5 05/30] ARM: GICv3: allocate LPI pending and property table

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> The ARM GICv3 provides a new kind of interrupt called LPIs.
> The pending bits and the configuration data (priority, enable bits) for
> those LPIs are stored in tables in normal memory, which software has to
> provide to the hardware.
> Allocate the required memory, initialize it and hand it over to each
> redistributor. The maximum number of LPIs to be used can be adjusted with
> the command line option "max_lpi_bits", which defaults to 20 bits,
> covering about one million LPIs.
> 
> Signed-off-by: Andre Przywara 

Reviewed-by: Stefano Stabellini 

> ---
>  docs/misc/xen-command-line.markdown |   9 ++
>  xen/arch/arm/Makefile   |   1 +
>  xen/arch/arm/gic-v3-lpi.c   | 221 
> 
>  xen/arch/arm/gic-v3.c   |  17 +++
>  xen/include/asm-arm/gic_v3_defs.h   |  52 +
>  xen/include/asm-arm/gic_v3_its.h|  15 ++-
>  xen/include/asm-arm/irq.h   |   8 ++
>  7 files changed, 322 insertions(+), 1 deletion(-)
>  create mode 100644 xen/arch/arm/gic-v3-lpi.c
> 
> diff --git a/docs/misc/xen-command-line.markdown 
> b/docs/misc/xen-command-line.markdown
> index 9eb85d6..6ef8633 100644
> --- a/docs/misc/xen-command-line.markdown
> +++ b/docs/misc/xen-command-line.markdown
> @@ -1172,6 +1172,15 @@ based interrupts. Any higher IRQs will be available 
> for use via PCI MSI.
>  ### maxcpus
>  > `= `
>  
> +### max\_lpi\_bits
> +> `= `
> +
> +Specifies the number of ARM GICv3 LPI interrupts to allocate on the host,
> +presented as the number of bits needed to encode it. This must be at least
> +14 and not exceed 32, and each LPI requires one byte (configuration) and
> +one pending bit to be allocated.
> +Defaults to 20 bits (to cover at most 1048576 interrupts).
> +
>  ### mce
>  > `= `
>  
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 39c0a03..6be85ab 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -19,6 +19,7 @@ obj-y += gic.o
>  obj-y += gic-v2.o
>  obj-$(CONFIG_HAS_GICV3) += gic-v3.o
>  obj-$(CONFIG_HAS_ITS) += gic-v3-its.o
> +obj-$(CONFIG_HAS_ITS) += gic-v3-lpi.o
>  obj-y += guestcopy.o
>  obj-y += hvm.o
>  obj-y += io.o
> diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
> new file mode 100644
> index 000..7f99ec6
> --- /dev/null
> +++ b/xen/arch/arm/gic-v3-lpi.c
> @@ -0,0 +1,221 @@
> +/*
> + * xen/arch/arm/gic-v3-lpi.c
> + *
> + * ARM GICv3 Locality-specific Peripheral Interrupts (LPI) support
> + *
> + * Copyright (C) 2016,2017 - ARM Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; under version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; If not, see .
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define LPI_PROPTABLE_NEEDS_FLUSHING(1U << 0)
> +
> +/* Global state */
> +static struct {
> +/* The global LPI property table, shared by all redistributors. */
> +uint8_t *lpi_property;
> +/*
> + * Number of physical LPIs the host supports. This is a property of
> + * the GIC hardware. We depart from the habit of naming these things
> + * "physical" in Xen, as the GICv3/4 spec uses the term "physical LPI"
> + * in a different context to differentiate them from "virtual LPIs".
> + */
> +unsigned long long int max_host_lpi_ids;
> +unsigned int flags;
> +} lpi_data;
> +
> +struct lpi_redist_data {
> +void*pending_table;
> +};
> +
> +static DEFINE_PER_CPU(struct lpi_redist_data, lpi_redist);
> +
> +#define MAX_NR_HOST_LPIS   (lpi_data.max_host_lpi_ids - LPI_OFFSET)
> +
> +static int gicv3_lpi_allocate_pendtable(uint64_t *reg)
> +{
> +uint64_t val;
> +void *pendtable;
> +
> +if ( this_cpu(lpi_redist).pending_table )
> +return -EBUSY;
> +
> +val  = GIC_BASER_CACHE_RaWaWb << GICR_PENDBASER_INNER_CACHEABILITY_SHIFT;
> +val |= GIC_BASER_CACHE_SameAsInner << 
> GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT;
> +val |= GIC_BASER_InnerShareable << GICR_PENDBASER_SHAREABILITY_SHIFT;
> +
> +/*
> + * The pending table holds one bit per LPI and even covers bits for
> + * interrupt IDs below 8192, so we allocate the full range.
> + * The GICv3 imposes a 64KB alignment requirement, also requires
> + * physically contiguous memory.
> + */
> +pendtable = 

Re: [Xen-devel] [PATCH v5 04/30] ARM: GICv3 ITS: initialize host ITS

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> Map the registers frame for each host ITS and populate the host ITS
> structure with some parameters describing the size of certain properties
> like the number of bits for device IDs.
> 
> Signed-off-by: Andre Przywara 

Reviewed-by: Stefano Stabellini 

> ---
>  xen/arch/arm/gic-v3-its.c| 33 ++
>  xen/arch/arm/gic-v3.c|  5 +
>  xen/include/asm-arm/gic_v3_its.h | 44 
> 
>  3 files changed, 82 insertions(+)
> 
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index 6b02349..0298866 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -19,8 +19,10 @@
>   */
>  
>  #include 
> +#include 
>  #include 
>  #include 
> +#include 
>  
>  /*
>   * No lock here, as this list gets only populated upon boot while scanning
> @@ -33,6 +35,37 @@ bool gicv3_its_host_has_its(void)
>  return !list_empty(_its_list);
>  }
>  
> +static int gicv3_its_init_single_its(struct host_its *hw_its)
> +{
> +uint64_t reg;
> +
> +hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size);
> +if ( !hw_its->its_base )
> +return -ENOMEM;
> +
> +reg = readq_relaxed(hw_its->its_base + GITS_TYPER);
> +hw_its->devid_bits = GITS_TYPER_DEVICE_ID_BITS(reg);
> +hw_its->evid_bits = GITS_TYPER_EVENT_ID_BITS(reg);
> +hw_its->itte_size = GITS_TYPER_ITT_SIZE(reg);
> +
> +return 0;
> +}
> +
> +int gicv3_its_init(void)
> +{
> +struct host_its *hw_its;
> +int ret;
> +
> +list_for_each_entry(hw_its, _its_list, entry)
> +{
> +ret = gicv3_its_init_single_its(hw_its);
> +if ( ret )
> +return ret;
> +}
> +
> +return 0;
> +}
> +
>  /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. 
> */
>  void gicv3_its_dt_init(const struct dt_device_node *node)
>  {
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index b626298..d3d5784 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -1590,6 +1590,11 @@ static int __init gicv3_init(void)
>  spin_lock();
>  
>  gicv3_dist_init();
> +
> +res = gicv3_its_init();
> +if ( res )
> +panic("GICv3: ITS: initialization failed: %d\n", res);
> +
>  res = gicv3_cpu_init();
>  gicv3_hyp_init();
>  
> diff --git a/xen/include/asm-arm/gic_v3_its.h 
> b/xen/include/asm-arm/gic_v3_its.h
> index 765a655..7d88987 100644
> --- a/xen/include/asm-arm/gic_v3_its.h
> +++ b/xen/include/asm-arm/gic_v3_its.h
> @@ -20,6 +20,38 @@
>  #ifndef __ASM_ARM_ITS_H__
>  #define __ASM_ARM_ITS_H__
>  
> +#define GITS_CTLR   0x000
> +#define GITS_IIDR   0x004
> +#define GITS_TYPER  0x008
> +#define GITS_CBASER 0x080
> +#define GITS_CWRITER0x088
> +#define GITS_CREADR 0x090
> +#define GITS_BASER_NR_REGS  8
> +#define GITS_BASER0 0x100
> +#define GITS_BASER1 0x108
> +#define GITS_BASER2 0x110
> +#define GITS_BASER3 0x118
> +#define GITS_BASER4 0x120
> +#define GITS_BASER5 0x128
> +#define GITS_BASER6 0x130
> +#define GITS_BASER7 0x138
> +
> +/* Register bits */
> +#define GITS_TYPER_DEVIDS_SHIFT 13
> +#define GITS_TYPER_DEVIDS_MASK  (0x1fUL << GITS_TYPER_DEVIDS_SHIFT)
> +#define GITS_TYPER_DEVICE_ID_BITS(r)(((r & GITS_TYPER_DEVIDS_MASK) >> \
> +   GITS_TYPER_DEVIDS_SHIFT) + 1)
> +
> +#define GITS_TYPER_IDBITS_SHIFT 8
> +#define GITS_TYPER_IDBITS_MASK  (0x1fUL << GITS_TYPER_IDBITS_SHIFT)
> +#define GITS_TYPER_EVENT_ID_BITS(r) (((r & GITS_TYPER_IDBITS_MASK) >> \
> +   GITS_TYPER_IDBITS_SHIFT) + 1)
> +
> +#define GITS_TYPER_ITT_SIZE_SHIFT   4
> +#define GITS_TYPER_ITT_SIZE_MASK(0xfUL << GITS_TYPER_ITT_SIZE_SHIFT)
> +#define GITS_TYPER_ITT_SIZE(r)  r) & GITS_TYPER_ITT_SIZE_MASK) 
> >> \
> + GITS_TYPER_ITT_SIZE_SHIFT) 
> + 1)
> +
>  #include 
>  
>  /* data structure for each hardware ITS */
> @@ -28,6 +60,10 @@ struct host_its {
>  const struct dt_device_node *dt_node;
>  paddr_t addr;
>  paddr_t size;
> +void __iomem *its_base;
> +unsigned int devid_bits;
> +unsigned int evid_bits;
> +unsigned int itte_size;
>  };
>  
>  
> @@ -40,6 +76,9 @@ void gicv3_its_dt_init(const struct dt_device_node *node);
>  
>  bool gicv3_its_host_has_its(void);
>  
> +/* Initialize the host structures for the host ITSes. */
> +int gicv3_its_init(void);
> +
>  #else
>  
>  static LIST_HEAD(host_its_list);
> @@ -53,6 +92,11 @@ static inline bool 

Re: [Xen-devel] [PATCH v5 02/30] bitops: add BIT_ULL variant

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> To safely handle 64-bit registers even on 32-bit systems, introduce
> a BIT_ULL variant (lifted from Linux).
> 
> Signed-off-by: Andre Przywara 

Reviewed-by: Stefano Stabellini 

> ---
>  xen/include/asm-arm/bitops.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/xen/include/asm-arm/bitops.h b/xen/include/asm-arm/bitops.h
> index bda8898..1cbfb9e 100644
> --- a/xen/include/asm-arm/bitops.h
> +++ b/xen/include/asm-arm/bitops.h
> @@ -24,6 +24,7 @@
>  #define BIT(nr) (1UL << (nr))
>  #define BIT_MASK(nr)(1UL << ((nr) % BITS_PER_WORD))
>  #define BIT_WORD(nr)((nr) / BITS_PER_WORD)
> +#define BIT_ULL(nr) (1ULL << (nr))
>  #define BITS_PER_BYTE   8
>  
>  #define ADDR (*(volatile int *) addr)
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 01/30] bitops: add GENMASK_ULL

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> To safely handle 64-bit registers even on 32-bit systems, introduce
> a GENMASK_ULL variant (lifted from Linux).
> This adds a BITS_PER_LONG_LONG define as well.
> Also fix a bug in the comment for the existing GENMASK variant.
> 
> Signed-off-by: Andre Przywara 

Reviewed-by: Stefano Stabellini 

> ---
>  xen/include/asm-arm/config.h | 2 ++
>  xen/include/xen/bitops.h | 5 -
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
> index b2edf95..1f730ce 100644
> --- a/xen/include/asm-arm/config.h
> +++ b/xen/include/asm-arm/config.h
> @@ -19,6 +19,8 @@
>  #define BITS_PER_LONG (BYTES_PER_LONG << 3)
>  #define POINTER_ALIGN BYTES_PER_LONG
>  
> +#define BITS_PER_LONG_LONG (sizeof (long long) * BITS_PER_BYTE)
> +
>  /* xen_ulong_t is always 64 bits */
>  #define BITS_PER_XEN_ULONG 64
>  
> diff --git a/xen/include/xen/bitops.h b/xen/include/xen/bitops.h
> index bd0883a..9261e06 100644
> --- a/xen/include/xen/bitops.h
> +++ b/xen/include/xen/bitops.h
> @@ -5,11 +5,14 @@
>  /*
>   * Create a contiguous bitmask starting at bit position @l and ending at
>   * position @h. For example
> - * GENMASK(30, 21) gives us the 32bit vector 0x01fe0.
> + * GENMASK(30, 21) gives us the 32bit vector 0x7fe0.
>   */
>  #define GENMASK(h, l) \
>  (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h
>  
> +#define GENMASK_ULL(h, l) \
> +(((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h
> +
>  /*
>   * ffs: find first bit set. This is defined the same way as
>   * the libc and compiler builtin ffs routines, therefore
> -- 
> 2.8.2
> 

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v5 03/30] ARM: GICv3 ITS: parse and store ITS subnodes from hardware DT

2017-04-05 Thread Stefano Stabellini
On Thu, 6 Apr 2017, Andre Przywara wrote:
> Parse the GIC subnodes in the device tree to find every ITS MSI controller
> the hardware offers. Store that information in a list to both propagate
> all of them later to Dom0, but also to be able to iterate over all ITSes.
> This introduces an ITS Kconfig option (as an EXPERT option), use
> XEN_CONFIG_EXPERT=y on the make command line to see and use the option.
> 
> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/Kconfig |  5 +++
>  xen/arch/arm/Makefile|  1 +
>  xen/arch/arm/gic-v3-its.c| 77 
> 
>  xen/arch/arm/gic-v3.c| 10 +++---
>  xen/include/asm-arm/gic_v3_its.h | 67 ++
>  5 files changed, 156 insertions(+), 4 deletions(-)
>  create mode 100644 xen/arch/arm/gic-v3-its.c
>  create mode 100644 xen/include/asm-arm/gic_v3_its.h
> 
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index 43123e6..d46b98c 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -45,6 +45,11 @@ config ACPI
>  config HAS_GICV3
>   bool
>  
> +config HAS_ITS
> +bool
> +prompt "GICv3 ITS MSI controller support" if EXPERT = "y"
> +depends on HAS_GICV3
> +
>  endmenu
>  
>  menu "ARM errata workaround via the alternative framework"
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 0ce94a8..39c0a03 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -18,6 +18,7 @@ obj-$(EARLY_PRINTK) += early_printk.o
>  obj-y += gic.o
>  obj-y += gic-v2.o
>  obj-$(CONFIG_HAS_GICV3) += gic-v3.o
> +obj-$(CONFIG_HAS_ITS) += gic-v3-its.o
>  obj-y += guestcopy.o
>  obj-y += hvm.o
>  obj-y += io.o
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> new file mode 100644
> index 000..6b02349
> --- /dev/null
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -0,0 +1,77 @@
> +/*
> + * xen/arch/arm/gic-v3-its.c
> + *
> + * ARM GICv3 Interrupt Translation Service (ITS) support
> + *
> + * Copyright (C) 2016,2017 - ARM Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; under version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; If not, see .
> + */
> +
> +#include 
> +#include 
> +#include 
> +
> +/*
> + * No lock here, as this list gets only populated upon boot while scanning
> + * firmware tables for all host ITSes, and only gets iterated afterwards.
> + */
> +LIST_HEAD(host_its_list);
> +
> +bool gicv3_its_host_has_its(void)
> +{
> +return !list_empty(_its_list);
> +}
> +
> +/* Scan the DT for any ITS nodes and create a list of host ITSes out of it. 
> */
> +void gicv3_its_dt_init(const struct dt_device_node *node)
> +{
> +const struct dt_device_node *its = NULL;
> +struct host_its *its_data;
> +
> +/*
> + * Check for ITS MSI subnodes. If any, add the ITS register
> + * frames to the ITS list.
> + */
> +dt_for_each_child_node(node, its)
> +{
> +uint64_t addr, size;
> +
> +if ( !dt_device_is_compatible(its, "arm,gic-v3-its") )
> +continue;
> +
> +if ( dt_device_get_address(its, 0, , ) )
> +panic("GICv3: Cannot find a valid ITS frame address");
> +
> +its_data = xzalloc(struct host_its);
> +if ( !its_data )
> +panic("GICv3: Cannot allocate memory for ITS frame");
> +
> +its_data->addr = addr;
> +its_data->size = size;
> +its_data->dt_node = its;
> +
> +printk("GICv3: Found ITS @0x%lx\n", addr);
> +
> +list_add_tail(_data->entry, _its_list);
> +}
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index 695f01f..b626298 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -42,6 +42,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  
> @@ -1227,11 +1228,12 @@ static void __init gicv3_dt_init(void)
>   */
>  res = dt_device_get_address(node, 1 + gicv3.rdist_count,
>  , );
> -if ( res )
> -return;
> +if ( !res )
> +dt_device_get_address(node, 1 + gicv3.rdist_count + 2,
> +  , );
>  
> -dt_device_get_address(node, 1 + gicv3.rdist_count + 2,
> -  , );
> +/* Check for ITS child nodes 

Re: [Xen-devel] [PATCH v4 23/27] ARM: vITS: handle INV command

2017-04-05 Thread André Przywara
On 04/04/17 17:51, Julien Grall wrote:
> Hi Andre,
> 
> On 03/04/17 21:28, Andre Przywara wrote:
>> The INV command instructs the ITS to update the configuration data for
>> a given LPI by re-reading its entry from the property table.
>> We don't need to care so much about the priority value, but enabling
>> or disabling an LPI has some effect: We remove or push virtual LPIs
>> to their VCPUs, also check the virtual pending bit if an LPI gets
>> enabled.
>>
>> Signed-off-by: Andre Przywara 
>> ---
>>  xen/arch/arm/vgic-v3-its.c | 62
>> ++
>>  1 file changed, 62 insertions(+)
>>
>> diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
>> index 2f024b1..920c437 100644
>> --- a/xen/arch/arm/vgic-v3-its.c
>> +++ b/xen/arch/arm/vgic-v3-its.c

[ ... ]

>> +
>> +if ( *property & LPI_PROP_ENABLED )
>> +{
>> +unsigned long flags;
>> +
>> +set_bit(GIC_IRQ_GUEST_ENABLED, >status);
>> +spin_lock_irqsave(>arch.vgic.lock, flags);
>> +if ( !list_empty(>inflight) &&
>> + !test_bit(GIC_IRQ_GUEST_VISIBLE, >status) )
>> +gic_raise_guest_irq(vcpu, vlpi, p->lpi_priority);
>> +spin_unlock_irqrestore(>arch.vgic.lock, flags);
>> +
>> +/* Check whether the LPI has fired while the guest had it
>> disabled. */
>> +if ( test_and_clear_bit(GIC_IRQ_GUEST_LPI_PENDING, >status) )
>> +vgic_vcpu_inject_irq(vcpu, vlpi);
>> +}
>> +else
>> +{
>> +clear_bit(GIC_IRQ_GUEST_ENABLED, >status);
>> +gic_remove_from_queues(vcpu, vlpi);
>> +}
> 
> This could looks quite similar to vgic_{enable,disable}_irqs. This is a
> call to refactor the code there.

I tried it and it doesn't work easily, because the part that handles a
single (non-virtual) interrupt calls vgic_get_virq_type(), whose
parameters break the abstraction of a single interrupt.
Given that I am bit wary of bending a core GIC function just for the
sake of refactoring just a second user.

Cheers,
Andre.



___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 25/30] ARM: vITS: handle DISCARD command

2017-04-05 Thread Andre Przywara
The DISCARD command drops the connection between a DeviceID/EventID
and an LPI/collection pair.
We mark the respective structure entries as not allocated and make
sure that any queued IRQs are removed.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c | 32 
 1 file changed, 32 insertions(+)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 6afb915..47f2884 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -549,6 +549,35 @@ out_unlock:
 return ret;
 }
 
+static int its_handle_discard(struct virt_its *its, uint64_t *cmdptr)
+{
+uint32_t devid = its_cmd_get_deviceid(cmdptr);
+uint32_t eventid = its_cmd_get_id(cmdptr);
+struct pending_irq *pirq;
+struct vcpu *vcpu;
+uint32_t vlpi;
+
+if ( !read_itte(its, devid, eventid, , ) )
+return -1;
+
+pirq = its->d->arch.vgic.handler->lpi_to_pending(its->d, vlpi);
+if ( pirq )
+{
+clear_bit(GIC_IRQ_GUEST_QUEUED, >status);
+gic_remove_from_queues(vcpu, vlpi);
+}
+
+if ( !write_itte(its, devid, eventid, UNMAPPED_COLLECTION, INVALID_LPI,
+ NULL) )
+return -1;
+
+if ( !gicv3_assign_guest_event(its->d, its->doorbell_address,
+   devid, eventid, NULL, 0) )
+return -1;
+
+return 0;
+}
+
 #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
 
 /*
@@ -580,6 +609,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 case GITS_CMD_CLEAR:
 ret = its_handle_clear(its, command);
 break;
+case GITS_CMD_DISCARD:
+ret = its_handle_discard(its, command);
+break;
 case GITS_CMD_INT:
 ret = its_handle_int(its, command);
 break;
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 11/30] ARM: GICv3 ITS: introduce device mapping

2017-04-05 Thread Andre Przywara
The ITS uses device IDs to map LPIs to a device. Dom0 will later use
those IDs, which we directly pass on to the host.
For this we have to map each device that Dom0 may request to a host
ITS device with the same identifier.
Allocate the respective memory and enter each device into an rbtree to
later be able to iterate over it or to easily teardown guests.
Because device IDs are per ITS, we need to identify a virtual ITS. We
use the doorbell address for that purpose, as it is a nice architectural
MSI property and spares us handling with opaque pointer or break
the VGIC abstraction.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c| 263 +++
 xen/arch/arm/vgic-v3-its.c   |   3 +
 xen/include/asm-arm/domain.h |   3 +
 xen/include/asm-arm/gic_v3_its.h |  13 ++
 4 files changed, 282 insertions(+)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index eb47c9d..45bbfa7 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -36,6 +38,26 @@
  */
 LIST_HEAD(host_its_list);
 
+/*
+ * Describes a device which is using the ITS and is used by a guest.
+ * Since device IDs are per ITS (in contrast to vLPIs, which are per
+ * guest), we have to differentiate between different virtual ITSes.
+ * We use the doorbell address here, since this is a nice architectural
+ * property of MSIs in general and we can easily get to the base address
+ * of the ITS and look that up.
+ */
+struct its_devices {
+struct rb_node rbnode;
+struct host_its *hw_its;
+void *itt_addr;
+paddr_t guest_doorbell; /* Identifies the virtual ITS */
+uint32_t host_devid;
+uint32_t guest_devid;
+uint32_t eventids;  /* Number of event IDs (MSIs) */
+uint32_t *host_lpi_blocks;  /* Which LPIs are used on the host */
+struct pending_irq *pend_irqs;  /* One struct per event */
+};
+
 bool gicv3_its_host_has_its(void)
 {
 return !list_empty(_its_list);
@@ -185,6 +207,30 @@ static int its_send_cmd_mapc(struct host_its *its, 
uint32_t collection_id,
 return its_send_command(its, cmd);
 }
 
+static int its_send_cmd_mapd(struct host_its *its, uint32_t deviceid,
+ uint8_t size_bits, paddr_t itt_addr, bool valid)
+{
+uint64_t cmd[4];
+
+if ( valid )
+{
+ASSERT(size_bits <= its->evid_bits);
+ASSERT(size_bits > 0);
+ASSERT(!(itt_addr & ~GENMASK_ULL(51, 8)));
+
+/* The number of events is encoded as "number of bits minus one". */
+size_bits--;
+}
+cmd[0] = GITS_CMD_MAPD | ((uint64_t)deviceid << 32);
+cmd[1] = size_bits;
+cmd[2] = itt_addr;
+if ( valid )
+cmd[2] |= GITS_VALID_BIT;
+cmd[3] = 0x00;
+
+return its_send_command(its, cmd);
+}
+
 static int its_send_cmd_inv(struct host_its *its,
 uint32_t deviceid, uint32_t eventid)
 {
@@ -477,6 +523,66 @@ int gicv3_its_init(void)
 return 0;
 }
 
+static int remove_mapped_guest_device(struct its_devices *dev)
+{
+int ret = 0;
+unsigned int i;
+
+if ( dev->hw_its )
+/* MAPD also discards all events with this device ID. */
+ret = its_send_cmd_mapd(dev->hw_its, dev->host_devid, 0, 0, false);
+
+for ( i = 0; i < dev->eventids / LPI_BLOCK; i++ )
+gicv3_free_host_lpi_block(dev->host_lpi_blocks[i]);
+
+/* Make sure the MAPD command above is really executed. */
+if ( !ret )
+ret = gicv3_its_wait_commands(dev->hw_its);
+
+/* This should never happen, but just in case ... */
+if ( ret )
+printk(XENLOG_WARNING "Can't unmap host ITS device 0x%x\n",
+   dev->host_devid);
+
+xfree(dev->itt_addr);
+xfree(dev->pend_irqs);
+xfree(dev->host_lpi_blocks);
+xfree(dev);
+
+return 0;
+}
+
+static struct host_its *gicv3_its_find_by_doorbell(paddr_t doorbell_address)
+{
+struct host_its *hw_its;
+
+list_for_each_entry(hw_its, _its_list, entry)
+{
+if ( hw_its->addr + ITS_DOORBELL_OFFSET == doorbell_address )
+return hw_its;
+}
+
+return NULL;
+}
+
+static int compare_its_guest_devices(struct its_devices *dev,
+ paddr_t vdoorbell, uint32_t vdevid)
+{
+if ( dev->guest_doorbell < vdoorbell )
+return -1;
+
+if ( dev->guest_doorbell > vdoorbell )
+return 1;
+
+if ( dev->guest_devid < vdevid )
+return -1;
+
+if ( dev->guest_devid > vdevid )
+return 1;
+
+return 0;
+}
+
 /*
  * On the host ITS @its, map @nr_events consecutive LPIs.
  * The mapping connects a device @devid and event @eventid pair to LPI @lpi,
@@ -510,6 +616,163 @@ static int gicv3_its_map_host_events(struct host_its *its,
 return gicv3_its_wait_commands(its);
 }
 
+/*
+ * Map a hardware device, identified 

[Xen-devel] [PATCH v5 14/30] ARM: GICv3: enable ITS and LPIs on the host

2017-04-05 Thread Andre Przywara
Now that the host part of the ITS code is in place, we can enable the
ITS and also LPIs on each redistributor to get the show rolling.
At this point there would be no LPIs mapped, as guests don't know about
the ITS yet.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c |  4 
 xen/arch/arm/gic-v3.c | 18 ++
 2 files changed, 22 insertions(+)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 45bbfa7..76b0316 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -505,6 +505,10 @@ static int gicv3_its_init_single_its(struct host_its 
*hw_its)
 return -ENOMEM;
 writeq_relaxed(0, hw_its->its_base + GITS_CWRITER);
 
+/* Now enable interrupt translation and command processing on that ITS. */
+reg = readl_relaxed(hw_its->its_base + GITS_CTLR);
+writel_relaxed(reg | GITS_CTLR_ENABLE, hw_its->its_base + GITS_CTLR);
+
 return 0;
 }
 
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 63dbc21..54fbb19 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -620,6 +620,21 @@ static int gicv3_enable_redist(void)
 return 0;
 }
 
+/* Enable LPIs on this redistributor (only useful when the host has an ITS). */
+static bool gicv3_enable_lpis(void)
+{
+uint32_t val;
+
+val = readl_relaxed(GICD_RDIST_BASE + GICR_TYPER);
+if ( !(val & GICR_TYPER_PLPIS) )
+return false;
+
+val = readl_relaxed(GICD_RDIST_BASE + GICR_CTLR);
+writel_relaxed(val | GICR_CTLR_ENABLE_LPIS, GICD_RDIST_BASE + GICR_CTLR);
+
+return true;
+}
+
 static int __init gicv3_populate_rdist(void)
 {
 int i;
@@ -731,11 +746,14 @@ static int gicv3_cpu_init(void)
 if ( gicv3_enable_redist() )
 return -ENODEV;
 
+/* If the host has any ITSes, enable LPIs now. */
 if ( gicv3_its_host_has_its() )
 {
 ret = gicv3_its_setup_collection(smp_processor_id());
 if ( ret )
 return ret;
+if ( !gicv3_enable_lpis() )
+return -EBUSY;
 }
 
 /* Set priority on PPI and SGI interrupts */
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 13/30] ARM: GICv3: forward pending LPIs to guests

2017-04-05 Thread Andre Przywara
Upon receiving an LPI on the host, we need to find the right VCPU and
virtual IRQ number to get this IRQ injected.
Iterate our two-level LPI table to find this information quickly when
the host takes an LPI. Call the existing injection function to let the
GIC emulation deal with this interrupt.
Also we enhance struct pending_irq to cache the pending bit and the
priority information for LPIs, as we can't afford to walk the tables in
guest memory every time we handle an incoming LPI.
This introduces a do_LPI() as a hardware gic_ops and a function to
retrieve the (cached) priority value of an LPI and a vgic_ops.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v2.c|  7 +
 xen/arch/arm/gic-v3-lpi.c| 56 
 xen/arch/arm/gic-v3.c|  1 +
 xen/arch/arm/gic.c   |  8 +-
 xen/arch/arm/vgic-v2.c   |  7 +
 xen/arch/arm/vgic-v3.c   | 12 +
 xen/arch/arm/vgic.c  |  7 -
 xen/include/asm-arm/gic.h|  2 ++
 xen/include/asm-arm/gic_v3_its.h |  8 ++
 xen/include/asm-arm/vgic.h   |  3 +++
 10 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
index 270a136..f4d7949 100644
--- a/xen/arch/arm/gic-v2.c
+++ b/xen/arch/arm/gic-v2.c
@@ -1217,6 +1217,12 @@ static int __init gicv2_init(void)
 return 0;
 }
 
+void gicv2_do_LPI(unsigned int lpi)
+{
+/* No LPIs in a GICv2 */
+BUG();
+}
+
 const static struct gic_hw_operations gicv2_ops = {
 .info= _info,
 .init= gicv2_init,
@@ -1244,6 +1250,7 @@ const static struct gic_hw_operations gicv2_ops = {
 .make_hwdom_madt = gicv2_make_hwdom_madt,
 .map_hwdom_extra_mappings = gicv2_map_hwdown_extra_mappings,
 .iomem_deny_access   = gicv2_iomem_deny_access,
+.do_LPI  = gicv2_do_LPI,
 };
 
 /* Set up the GIC */
diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
index 0785701..d8baebc 100644
--- a/xen/arch/arm/gic-v3-lpi.c
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -136,6 +136,62 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool 
use_pta)
 return per_cpu(lpi_redist, cpu).redist_id << 16;
 }
 
+/*
+ * Handle incoming LPIs, which are a bit special, because they are potentially
+ * numerous and also only get injected into guests. Treat them specially here,
+ * by just looking up their target vCPU and virtual LPI number and hand it
+ * over to the injection function.
+ * Please note that LPIs are edge-triggered only, also have no active state,
+ * so spurious interrupts on the host side are no issue (we can just ignore
+ * them).
+ * Also a guest cannot expect that firing interrupts that haven't been
+ * fully configured yet will reach the CPU, so we don't need to care about
+ * this special case.
+ */
+void gicv3_do_LPI(unsigned int lpi)
+{
+struct domain *d;
+union host_lpi *hlpip, hlpi;
+struct vcpu *vcpu;
+
+/* EOI the LPI already. */
+WRITE_SYSREG32(lpi, ICC_EOIR1_EL1);
+
+/* Find out if a guest mapped something to this physical LPI. */
+hlpip = gic_get_host_lpi(lpi);
+if ( !hlpip )
+return;
+
+hlpi.data = read_u64_atomic(>data);
+
+/*
+ * Unmapped events are marked with an invalid LPI ID. We can safely
+ * ignore them, as they have no further state and no-one can expect
+ * to see them if they have not been mapped.
+ */
+if ( hlpi.virt_lpi == INVALID_LPI )
+return;
+
+d = rcu_lock_domain_by_id(hlpi.dom_id);
+if ( !d )
+return;
+
+/* Make sure we don't step beyond the vcpu array. */
+if ( hlpi.vcpu_id >= d->max_vcpus )
+{
+rcu_unlock_domain(d);
+return;
+}
+
+vcpu = d->vcpu[hlpi.vcpu_id];
+
+/* Check if the VCPU is ready to receive LPIs. */
+if ( vcpu->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
+vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
+
+rcu_unlock_domain(d);
+}
+
 static int gicv3_lpi_allocate_pendtable(uint64_t *reg)
 {
 uint64_t val;
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index a559e5e..63dbc21 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1670,6 +1670,7 @@ static const struct gic_hw_operations gicv3_ops = {
 .make_hwdom_dt_node  = gicv3_make_hwdom_dt_node,
 .make_hwdom_madt = gicv3_make_hwdom_madt,
 .iomem_deny_access   = gicv3_iomem_deny_access,
+.do_LPI  = gicv3_do_LPI,
 };
 
 static int __init gicv3_dt_preinit(struct dt_device_node *node, const void 
*data)
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 9522c6c..a56be34 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -697,7 +697,13 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
 do_IRQ(regs, irq, is_fiq);
 local_irq_disable();
 }
-else if (unlikely(irq < 16))
+else if ( is_lpi(irq) )
+{
+ 

[Xen-devel] [PATCH v5 26/30] ARM: vITS: handle INV command

2017-04-05 Thread Andre Przywara
The INV command instructs the ITS to update the configuration data for
a given LPI by re-reading its entry from the property table.
We don't need to care so much about the priority value, but enabling
or disabling an LPI has some effect: We remove or push virtual LPIs
to their VCPUs, also check the virtual pending bit if an LPI gets enabled.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c | 96 ++
 1 file changed, 96 insertions(+)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 47f2884..0d4b20d 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -376,6 +376,99 @@ static int its_handle_int(struct virt_its *its, uint64_t 
*cmdptr)
 return 0;
 }
 
+/*
+ * For a given virtual LPI read the enabled bit and priority from the virtual
+ * property table and update the virtual IRQ's state in the given pending_irq.
+ */
+static int update_lpi_property(struct domain *d, uint32_t vlpi,
+   struct pending_irq *p)
+{
+paddr_t addr;
+uint8_t property;
+int ret;
+
+addr = d->arch.vgic.rdist_propbase & GENMASK_ULL(51, 12);
+
+ret = vgic_access_guest_memory(d, addr + vlpi - LPI_OFFSET,
+   , sizeof(property), false);
+if ( ret )
+return ret;
+
+p->lpi_priority = property & LPI_PROP_PRIO_MASK;
+if ( property & LPI_PROP_ENABLED )
+set_bit(GIC_IRQ_GUEST_ENABLED, >status);
+else
+clear_bit(GIC_IRQ_GUEST_ENABLED, >status);
+
+return 0;
+}
+
+/*
+ * For a given virtual LPI read the enabled bit and priority from the virtual
+ * property table and update the virtual IRQ's state.
+ * This takes care of removing or pushing of virtual LPIs to their VCPUs.
+ * Also check if this LPI is due to be injected and do it, if needed.
+ */
+static int update_lpi_enabled_status(struct domain *d,
+ struct vcpu *vcpu, uint32_t vlpi)
+{
+struct pending_irq *p = d->arch.vgic.handler->lpi_to_pending(d, vlpi);
+unsigned long flags;
+int ret;
+
+if ( !p )
+return -EINVAL;
+
+spin_lock_irqsave(>arch.vgic.lock, flags);
+ret = update_lpi_property(d, vlpi, p);
+if ( ret ) {
+spin_unlock_irqrestore(>arch.vgic.lock, flags);
+return ret;
+}
+
+if ( test_bit(GIC_IRQ_GUEST_ENABLED, >status) )
+{
+if ( !list_empty(>inflight) &&
+ !test_bit(GIC_IRQ_GUEST_VISIBLE, >status) )
+gic_raise_guest_irq(vcpu, vlpi, p->lpi_priority);
+spin_unlock_irqrestore(>arch.vgic.lock, flags);
+
+/* Check whether the LPI has fired while the guest had it disabled. */
+if ( test_and_clear_bit(GIC_IRQ_GUEST_LPI_PENDING, >status) )
+vgic_vcpu_inject_irq(vcpu, vlpi);
+}
+else
+{
+clear_bit(GIC_IRQ_GUEST_ENABLED, >status);
+spin_unlock_irqrestore(>arch.vgic.lock, flags);
+
+gic_remove_from_queues(vcpu, vlpi);
+}
+
+return 0;
+}
+
+static int its_handle_inv(struct virt_its *its, uint64_t *cmdptr)
+{
+uint32_t devid = its_cmd_get_deviceid(cmdptr);
+uint32_t eventid = its_cmd_get_id(cmdptr);
+struct vcpu *vcpu;
+uint32_t vlpi;
+
+/* Translate the event into a vCPU/vLPI pair. */
+if ( !read_itte(its, devid, eventid, , ) )
+return -1;
+
+/*
+ * Now read the property table and update our cached status. This
+ * also takes care if this LPI now needs to be injected or removed.
+ */
+if ( update_lpi_enabled_status(its->d, vcpu, vlpi) )
+return -1;
+
+return 0;
+}
+
 static int its_handle_mapc(struct virt_its *its, uint64_t *cmdptr)
 {
 uint32_t collid = its_cmd_get_collection(cmdptr);
@@ -615,6 +708,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 case GITS_CMD_INT:
 ret = its_handle_int(its, command);
 break;
+case GITS_CMD_INV:
+ret = its_handle_inv(its, command);
+break;
 case GITS_CMD_MAPC:
 ret = its_handle_mapc(its, command);
 break;
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 19/30] ARM: vITS: handle CLEAR command

2017-04-05 Thread Andre Przywara
This introduces the ITS command handler for the CLEAR command, which
clears the pending state of an LPI.
This removes a not-yet injected, but already queued IRQ from a VCPU.
As read_itte() is now eventually used, we add the static keyword.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c | 49 --
 1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index a145666..71bc08a 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -191,8 +191,8 @@ static bool read_itte_locked(struct virt_its *its, uint32_t 
devid,
  * This function takes care of the locking by taking the its_lock itself, so
  * a caller shall not hold this. Before returning, the lock is dropped again.
  */
-bool read_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
-   struct vcpu **vcpu_ptr, uint32_t *vlpi_ptr)
+static bool read_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
+  struct vcpu **vcpu_ptr, uint32_t *vlpi_ptr)
 {
 bool ret;
 
@@ -277,6 +277,48 @@ static uint64_t its_cmd_mask_field(uint64_t *its_cmd, 
unsigned int word,
 #define its_cmd_get_validbit(cmd)   its_cmd_mask_field(cmd, 2, 63,  1)
 #define its_cmd_get_ittaddr(cmd)(its_cmd_mask_field(cmd, 2, 8, 44) << 
8)
 
+/*
+ * CLEAR removes the pending state from an LPI. */
+static int its_handle_clear(struct virt_its *its, uint64_t *cmdptr)
+{
+uint32_t devid = its_cmd_get_deviceid(cmdptr);
+uint32_t eventid = its_cmd_get_id(cmdptr);
+struct pending_irq *p;
+struct vcpu *vcpu;
+uint32_t vlpi;
+unsigned long flags;
+
+/* Translate the DevID/EvID pair into a vCPU/vLPI pair. */
+if ( !read_itte(its, devid, eventid, , ) )
+return -1;
+
+p = its->d->arch.vgic.handler->lpi_to_pending(its->d, vlpi);
+if ( !p )
+return -1;
+
+spin_lock_irqsave(>arch.vgic.lock, flags);
+
+/* We store the pending bit for LPIs in our struct pending_irq. */
+clear_bit(GIC_IRQ_GUEST_LPI_PENDING, >status);
+
+/*
+ * If the LPI is already visible on the guest, it is too late to
+ * clear the pending state. However this is a benign race that can
+ * happen on real hardware, too: If the LPI has already been forwarded
+ * to a CPU interface, a CLEAR request reaching the redistributor has
+ * no effect on that LPI anymore. Since LPIs are edge triggered and
+ * have no active state, we don't need to care about this here.
+ */
+if ( !test_bit(GIC_IRQ_GUEST_VISIBLE, >status) )
+{
+/* Remove a pending, but not yet injected guest IRQ. */
+clear_bit(GIC_IRQ_GUEST_QUEUED, >status);
+gic_remove_from_queues(vcpu, vlpi);
+}
+
+return 0;
+}
+
 #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
 
 /*
@@ -305,6 +347,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 
 switch ( its_cmd_get_command(command) )
 {
+case GITS_CMD_CLEAR:
+ret = its_handle_clear(its, command);
+break;
 case GITS_CMD_SYNC:
 /* We handle ITS commands synchronously, so we ignore SYNC. */
 break;
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 28/30] ARM: vITS: create and initialize virtual ITSes for Dom0

2017-04-05 Thread Andre Przywara
For each hardware ITS create and initialize a virtual ITS for Dom0.
We use the same memory mapped address to keep the doorbell working.
This introduces a function to initialize a virtual ITS.
We maintain a list of virtual ITSes, at the moment for the only
purpose of later being able to free them again.
We advertise 24 bits worth of LPIs on the guest side, using the full
32 bits seems to trigger a Linux bug (to be investigated).

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c   | 46 
 xen/arch/arm/vgic-v3.c   | 17 +++
 xen/include/asm-arm/domain.h |  2 ++
 xen/include/asm-arm/gic_v3_its.h | 12 +++
 4 files changed, 77 insertions(+)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 9684b3a..4e66cad 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -42,6 +42,7 @@
  */
 struct virt_its {
 struct domain *d;
+struct list_head vits_list;
 paddr_t doorbell_address;
 unsigned int devid_bits;
 unsigned int intid_bits;
@@ -72,12 +73,20 @@ struct vits_itte
 
 void vgic_v3_its_init_domain(struct domain *d)
 {
+INIT_LIST_HEAD(>arch.vgic.vits_list);
 spin_lock_init(>arch.vgic.its_devices_lock);
 d->arch.vgic.its_devices = RB_ROOT;
 }
 
 void vgic_v3_its_free_domain(struct domain *d)
 {
+struct virt_its *pos, *temp;
+
+list_for_each_entry_safe( pos, temp, >arch.vgic.vits_list, vits_list )
+{
+list_del(>vits_list);
+xfree(pos);
+}
 ASSERT(RB_EMPTY_ROOT(>arch.vgic.its_devices));
 }
 
@@ -1157,6 +1166,43 @@ static const struct mmio_handler_ops 
vgic_its_mmio_handler = {
 .write = vgic_v3_its_mmio_write,
 };
 
+int vgic_v3_its_init_virtual(struct domain *d, paddr_t guest_addr,
+ unsigned int devid_bits, unsigned int intid_bits)
+{
+struct virt_its *its;
+uint64_t base_attr;
+
+its = xzalloc(struct virt_its);
+if ( !its )
+return -ENOMEM;
+
+base_attr  = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT;
+base_attr |= GIC_BASER_CACHE_SameAsInner << 
GITS_BASER_OUTER_CACHEABILITY_SHIFT;
+base_attr |= GIC_BASER_CACHE_RaWaWb << GITS_BASER_INNER_CACHEABILITY_SHIFT;
+
+its->cbaser  = base_attr;
+base_attr |= 0ULL << GITS_BASER_PAGE_SIZE_SHIFT;/* 4K pages */
+its->baser_dev = GITS_BASER_TYPE_DEVICE << GITS_BASER_TYPE_SHIFT;
+its->baser_dev |= (sizeof(uint64_t) - 1) << GITS_BASER_ENTRY_SIZE_SHIFT;
+its->baser_dev |= base_attr;
+its->baser_coll  = GITS_BASER_TYPE_COLLECTION << GITS_BASER_TYPE_SHIFT;
+its->baser_coll |= (sizeof(uint16_t) - 1) << GITS_BASER_ENTRY_SIZE_SHIFT;
+its->baser_coll |= base_attr;
+its->d = d;
+its->doorbell_address = guest_addr + ITS_DOORBELL_OFFSET;
+its->devid_bits = devid_bits;
+its->intid_bits = intid_bits;
+spin_lock_init(>vcmd_lock);
+spin_lock_init(>its_lock);
+
+register_mmio_handler(d, _its_mmio_handler, guest_addr, SZ_64K, its);
+
+/* Register the virtual ITSes to be able to clean them up later. */
+list_add_tail(>vits_list, >arch.vgic.vits_list);
+
+return 0;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index e6a33d0..3b01247 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1569,6 +1570,7 @@ static int vgic_v3_domain_init(struct domain *d)
  */
 if ( is_hardware_domain(d) )
 {
+struct host_its *hw_its;
 unsigned int first_cpu = 0;
 
 d->arch.vgic.dbase = vgic_v3_hw.dbase;
@@ -1594,6 +1596,21 @@ static int vgic_v3_domain_init(struct domain *d)
 
 first_cpu += size / d->arch.vgic.rdist_stride;
 }
+d->arch.vgic.nr_regions = vgic_v3_hw.nr_rdist_regions;
+
+list_for_each_entry(hw_its, _its_list, entry)
+{
+/*
+ * For each host ITS create a virtual ITS using the same
+ * base and thus doorbell address.
+ * Use the same number of device ID bits as the host, and
+ * allow 24 bits for the interrupt ID.
+ */
+vgic_v3_its_init_virtual(d, hw_its->addr, hw_its->devid_bits, 24);
+
+d->arch.vgic.has_its = true;
+}
+
 }
 else
 {
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index f993292..cbbfb99 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -115,6 +115,8 @@ struct arch_domain
 spinlock_t its_devices_lock;/* Protects the its_devices tree */
 struct radix_tree_root pend_lpi_tree; /* Stores struct pending_irq's */
 rwlock_t pend_lpi_tree_lock;/* Protects the pend_lpi_tree */
+struct list_head vits_list; /* List of virtual ITSes */
+bool has_its;
 

[Xen-devel] [PATCH v5 08/30] ARM: GICv3 ITS: introduce ITS command handling

2017-04-05 Thread Andre Przywara
To be able to easily send commands to the ITS, create the respective
wrapper functions, which take care of the ring buffer.
The first two commands we implement provide methods to map a collection
to a redistributor (aka host core) and to flush the command queue (SYNC).
Start using these commands for mapping one collection to each host CPU.
As an ITS might choose between *two* ways of addressing a redistributor,
we store both the MMIO base address as well as the processor number in
a per-CPU variable to give each ITS what it wants.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c | 199 ++
 xen/arch/arm/gic-v3-lpi.c |  28 ++
 xen/arch/arm/gic-v3.c |  26 -
 xen/include/asm-arm/gic_v3_defs.h |   2 +
 xen/include/asm-arm/gic_v3_its.h  |  37 +++
 5 files changed, 291 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index d8e978a..1ecd63b 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -19,11 +19,14 @@
  */
 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 
 #define ITS_CMD_QUEUE_SZSZ_1M
 
@@ -38,6 +41,160 @@ bool gicv3_its_host_has_its(void)
 return !list_empty(_its_list);
 }
 
+#define BUFPTR_MASK GENMASK_ULL(19, 5)
+static int its_send_command(struct host_its *hw_its, const void *its_cmd)
+{
+/*
+ * The command queue should actually never become full, if it does anyway
+ * and this situation is not resolved quickly, this points to a much
+ * bigger problem, probably an hardware error.
+ * So to cover the one-off case where we actually hit a full command
+ * queue, we introduce a small grace period to not give up too quickly.
+ * Given the usual multi-hundred MHz frequency the ITS usually runs with,
+ * one millisecond (for a single command) seem to be more than enough.
+ * But this value is rather arbitrarily chosen based on theoretical
+ * considerations.
+ */
+s_time_t deadline = NOW() + MILLISECS(1);
+uint64_t readp, writep;
+int ret = -EBUSY;
+
+/* No ITS commands from an interrupt handler (at the moment). */
+ASSERT(!in_irq());
+
+spin_lock(_its->cmd_lock);
+
+do {
+readp = readq_relaxed(hw_its->its_base + GITS_CREADR) & BUFPTR_MASK;
+writep = readq_relaxed(hw_its->its_base + GITS_CWRITER) & BUFPTR_MASK;
+
+if ( ((writep + ITS_CMD_SIZE) % ITS_CMD_QUEUE_SZ) != readp )
+{
+ret = 0;
+break;
+}
+
+/*
+ * If the command queue is full, wait for a bit in the hope it drains
+ * before giving up.
+ */
+spin_unlock(_its->cmd_lock);
+cpu_relax();
+udelay(1);
+spin_lock(_its->cmd_lock);
+} while ( NOW() <= deadline );
+
+if ( ret )
+{
+spin_unlock(_its->cmd_lock);
+if ( printk_ratelimit() )
+printk(XENLOG_WARNING "host ITS: command queue full.\n");
+return ret;
+}
+
+memcpy(hw_its->cmd_buf + writep, its_cmd, ITS_CMD_SIZE);
+if ( hw_its->flags & HOST_ITS_FLUSH_CMD_QUEUE )
+clean_and_invalidate_dcache_va_range(hw_its->cmd_buf + writep,
+ ITS_CMD_SIZE);
+else
+dsb(ishst);
+
+writep = (writep + ITS_CMD_SIZE) % ITS_CMD_QUEUE_SZ;
+writeq_relaxed(writep & BUFPTR_MASK, hw_its->its_base + GITS_CWRITER);
+
+spin_unlock(_its->cmd_lock);
+
+return 0;
+}
+
+/* Wait for an ITS to finish processing all commands. */
+static int gicv3_its_wait_commands(struct host_its *hw_its)
+{
+/*
+ * As there could be quite a number of commands in a queue, we will
+ * wait a bit longer than the one millisecond for a single command above.
+ * Again this value is based on theoretical considerations, actually the
+ * command queue should drain much faster.
+ */
+s_time_t deadline = NOW() + MILLISECS(100);
+uint64_t readp, writep;
+
+do {
+spin_lock(_its->cmd_lock);
+readp = readq_relaxed(hw_its->its_base + GITS_CREADR) & BUFPTR_MASK;
+writep = readq_relaxed(hw_its->its_base + GITS_CWRITER) & BUFPTR_MASK;
+spin_unlock(_its->cmd_lock);
+
+if ( readp == writep )
+return 0;
+
+cpu_relax();
+udelay(1);
+} while ( NOW() <= deadline );
+
+return -ETIMEDOUT;
+}
+
+static uint64_t encode_rdbase(struct host_its *hw_its, unsigned int cpu,
+  uint64_t reg)
+{
+reg &= ~GENMASK_ULL(51, 16);
+
+reg |= gicv3_get_redist_address(cpu, hw_its->flags & HOST_ITS_USES_PTA);
+
+return reg;
+}
+
+static int its_send_cmd_sync(struct host_its *its, unsigned int cpu)
+{
+uint64_t cmd[4];
+
+cmd[0] = GITS_CMD_SYNC;
+cmd[1] = 0x00;
+cmd[2] = encode_rdbase(its, cpu, 0x0);
+cmd[3] = 0x00;
+
+return 

[Xen-devel] [PATCH v5 10/30] ARM: vGICv3: introduce ITS emulation stub

2017-04-05 Thread Andre Przywara
Create a new file to hold the emulation code for the ITS widget.
This just holds the data structure and a init and free function for now.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/Makefile|  1 +
 xen/arch/arm/vgic-v3-its.c   | 85 
 xen/arch/arm/vgic-v3.c   |  3 ++
 xen/include/asm-arm/gic_v3_its.h | 12 ++
 4 files changed, 101 insertions(+)
 create mode 100644 xen/arch/arm/vgic-v3-its.c

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 6be85ab..49e1fb2 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -47,6 +47,7 @@ obj-y += traps.o
 obj-y += vgic.o
 obj-y += vgic-v2.o
 obj-$(CONFIG_HAS_GICV3) += vgic-v3.o
+obj-$(CONFIG_HAS_ITS) += vgic-v3-its.o
 obj-y += vm_event.o
 obj-y += vtimer.o
 obj-y += vpsci.o
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
new file mode 100644
index 000..94c3c44
--- /dev/null
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -0,0 +1,85 @@
+/*
+ * xen/arch/arm/vgic-v3-its.c
+ *
+ * ARM Interrupt Translation Service (ITS) emulation
+ *
+ * Andre Przywara 
+ * Copyright (c) 2016,2017 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see .
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Data structure to describe a virtual ITS.
+ * If both the vcmd_lock and the its_lock are required, the vcmd_lock must
+ * be taken first.
+ */
+struct virt_its {
+struct domain *d;
+unsigned int devid_bits;
+unsigned int intid_bits;
+spinlock_t vcmd_lock;   /* Protects the virtual command buffer, which 
*/
+uint64_t cwriter;   /* consists of CBASER and CWRITER and those   
*/
+uint64_t creadr;/* shadow variables cwriter and creadr. */
+/* Protects the rest of this structure, including the ITS tables. */
+spinlock_t its_lock;
+uint64_t cbaser;
+uint64_t baser_dev, baser_coll; /* BASER0 and BASER1 for the guest */
+unsigned int max_collections;
+unsigned int max_devices;
+bool enabled;
+};
+
+/*
+ * An Interrupt Translation Table Entry: this is indexed by a
+ * DeviceID/EventID pair and is located in guest memory.
+ */
+struct vits_itte
+{
+uint32_t vlpi;
+uint16_t collection;
+uint16_t pad;
+};
+
+void vgic_v3_its_init_domain(struct domain *d)
+{
+}
+
+void vgic_v3_its_free_domain(struct domain *d)
+{
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 0679e76..142eb64 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1449,6 +1449,8 @@ static int vgic_v3_domain_init(struct domain *d)
 d->arch.vgic.nr_regions = rdist_count;
 d->arch.vgic.rdist_regions = rdist_regions;
 
+vgic_v3_its_init_domain(d);
+
 /*
  * Domain 0 gets the hardware address.
  * Guests get the virtual platform layout.
@@ -1521,6 +1523,7 @@ static int vgic_v3_domain_init(struct domain *d)
 
 static void vgic_v3_domain_free(struct domain *d)
 {
+vgic_v3_its_free_domain(d);
 xfree(d->arch.vgic.rdist_regions);
 }
 
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index 13b3e14..9b0c0ec 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -149,6 +149,10 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool 
use_pta);
 /* Map a collection for this host CPU to each host ITS. */
 int gicv3_its_setup_collection(unsigned int cpu);
 
+/* Initialize and destroy the per-domain parts of the virtual ITS support. */
+void vgic_v3_its_init_domain(struct domain *d);
+void vgic_v3_its_free_domain(struct domain *d);
+
 int gicv3_allocate_host_lpi_block(struct domain *d, uint32_t *first_lpi);
 void gicv3_free_host_lpi_block(uint32_t first_lpi);
 
@@ -191,6 +195,14 @@ static inline int gicv3_its_setup_collection(unsigned int 
cpu)
 BUG();
 }
 
+static inline void vgic_v3_its_init_domain(struct domain *d)
+{
+}
+
+static inline void vgic_v3_its_free_domain(struct domain *d)
+{
+}
+
 #endif /* CONFIG_HAS_ITS */
 
 #endif
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org

[Xen-devel] [PATCH v5 22/30] ARM: vITS: handle MAPD command

2017-04-05 Thread Andre Przywara
The MAPD command maps a device by associating a memory region for
storing ITEs with a certain device ID.
We store the given guest physical address in the device table, and, if
this command comes from Dom0, tell the host ITS driver about this new
mapping, so it can issue the corresponding host MAPD command and create
the required tables.
We simply use our existing guest memory access function to find the
right ITT entry and store the mapping there.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c | 59 ++
 1 file changed, 59 insertions(+)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index bbca5cf..0372ed0 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -42,6 +42,7 @@
  */
 struct virt_its {
 struct domain *d;
+paddr_t doorbell_address;
 unsigned int devid_bits;
 unsigned int intid_bits;
 spinlock_t vcmd_lock;   /* Protects the virtual command buffer, which 
*/
@@ -144,6 +145,20 @@ static struct vcpu *get_vcpu_from_collection(struct 
virt_its *its,
 #define DEV_TABLE_ENTRY(addr, bits) \
 (((addr) & GENMASK_ULL(51, 8)) | (((bits) - 1) & GENMASK_ULL(7, 0)))
 
+/* Set the address of an ITT for a given device ID. */
+static int its_set_itt_address(struct virt_its *its, uint32_t devid,
+   paddr_t itt_address, uint32_t nr_bits)
+{
+paddr_t addr = get_baser_phys_addr(its->baser_dev);
+uint64_t itt_entry = DEV_TABLE_ENTRY(itt_address, nr_bits);
+
+if ( devid >= its->max_devices )
+return -ENOENT;
+
+return vgic_access_guest_memory(its->d, addr + devid * sizeof(uint64_t),
+_entry, sizeof(itt_entry), true);
+}
+
 /*
  * Lookup the address of the Interrupt Translation Table associated with
  * a device ID and return the address of the ITTE belonging to the event ID
@@ -384,6 +399,47 @@ static int its_handle_mapc(struct virt_its *its, uint64_t 
*cmdptr)
 return 0;
 }
 
+static int its_handle_mapd(struct virt_its *its, uint64_t *cmdptr)
+{
+/* size and devid get validated by the functions called below. */
+uint32_t devid = its_cmd_get_deviceid(cmdptr);
+unsigned int size = its_cmd_get_size(cmdptr) + 1;
+bool valid = its_cmd_get_validbit(cmdptr);
+paddr_t itt_addr = its_cmd_get_ittaddr(cmdptr);
+int ret;
+
+/*
+ * There is no easy and clean way for Xen to know the ITS device ID of a
+ * particular (PCI) device, so we have to rely on the guest telling
+ * us about it. For *now* we are just using the device ID *Dom0* uses,
+ * because the driver there has the actual knowledge.
+ * Eventually this will be replaced with a dedicated hypercall to
+ * announce pass-through of devices.
+ */
+if ( is_hardware_domain(its->d) )
+{
+/*
+ * Dom0's ITSes are mapped 1:1, so both addresses are the same.
+ * Also the device IDs are equal.
+ */
+ret = gicv3_its_map_guest_device(its->d, its->doorbell_address, devid,
+ its->doorbell_address, devid,
+ BIT(size), valid);
+if ( ret )
+return ret;
+}
+
+spin_lock(>its_lock);
+if ( valid )
+ret = its_set_itt_address(its, devid, itt_addr, size);
+else
+ret = its_set_itt_address(its, devid, INVALID_PADDR, 1);
+
+spin_unlock(>its_lock);
+
+return ret;
+}
+
 #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
 
 /*
@@ -421,6 +477,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 case GITS_CMD_MAPC:
 ret = its_handle_mapc(its, command);
 break;
+case GITS_CMD_MAPD:
+ret = its_handle_mapd(its, command);
+break;
 case GITS_CMD_SYNC:
 /* We handle ITS commands synchronously, so we ignore SYNC. */
 break;
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 18/30] ARM: vITS: introduce translation table walks

2017-04-05 Thread Andre Przywara
The ITS stores the target (v)CPU and the (virtual) LPI number in tables.
Introduce functions to walk those tables and translate an device ID -
event ID pair into a pair of virtual LPI and vCPU.
We map those tables on demand - which is cheap on arm64. Also we take
care of the locking on the way, since we can't easily protect those ITTs
from being altered by the guest.

To allow compiling without warnings, we declare two functions as
non-static for the moment, which two later patches will fix.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic.c |   2 +
 xen/arch/arm/vgic-v3-its.c | 179 +
 2 files changed, 181 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index a56be34..5000b0d 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -491,6 +491,8 @@ static void gic_update_one_lr(struct vcpu *v, int i)
 {
 gic_hw_ops->clear_lr(i);
 clear_bit(i, _cpu(lr_mask));
+if ( is_lpi(irq) )
+clear_bit(GIC_IRQ_GUEST_LPI_PENDING, >status);
 
 if ( p->desc != NULL )
 clear_bit(_IRQ_INPROGRESS, >desc->status);
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index f6bf1ee..a145666 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -67,6 +67,8 @@ struct vits_itte
 uint16_t pad;
 };
 
+#define UNMAPPED_COLLECTION  ((uint16_t)~0)
+
 void vgic_v3_its_init_domain(struct domain *d)
 {
 spin_lock_init(>arch.vgic.its_devices_lock);
@@ -78,6 +80,183 @@ void vgic_v3_its_free_domain(struct domain *d)
 ASSERT(RB_EMPTY_ROOT(>arch.vgic.its_devices));
 }
 
+/*
+ * The physical address is encoded slightly differently depending on
+ * the used page size: the highest four bits are stored in the lowest
+ * four bits of the field for 64K pages.
+ */
+static paddr_t get_baser_phys_addr(uint64_t reg)
+{
+if ( reg & BIT(9) )
+return (reg & GENMASK_ULL(47, 16)) |
+((reg & GENMASK_ULL(15, 12)) << 36);
+else
+return reg & GENMASK_ULL(47, 12);
+}
+
+/* Must be called with the ITS lock held. */
+static struct vcpu *get_vcpu_from_collection(struct virt_its *its,
+ uint16_t collid)
+{
+paddr_t addr = get_baser_phys_addr(its->baser_coll);
+uint16_t vcpu_id;
+int ret;
+
+ASSERT(spin_is_locked(>its_lock));
+
+if ( collid >= its->max_collections )
+return NULL;
+
+ret = vgic_access_guest_memory(its->d, addr + collid * sizeof(uint16_t),
+   _id, sizeof(vcpu_id), false);
+if ( ret )
+return NULL;
+
+if ( vcpu_id == UNMAPPED_COLLECTION || vcpu_id >= its->d->max_vcpus )
+return NULL;
+
+return its->d->vcpu[vcpu_id];
+}
+
+/*
+ * Our device table encodings:
+ * Contains the guest physical address of the Interrupt Translation Table in
+ * bits [51:8], and the size of it is encoded as the number of bits minus one
+ * in the lowest 8 bits of the word.
+ */
+#define DEV_TABLE_ITT_ADDR(x) ((x) & GENMASK_ULL(51, 8))
+#define DEV_TABLE_ITT_SIZE(x) (BIT(((x) & GENMASK_ULL(7, 0)) + 1))
+#define DEV_TABLE_ENTRY(addr, bits) \
+(((addr) & GENMASK_ULL(51, 8)) | (((bits) - 1) & GENMASK_ULL(7, 0)))
+
+/*
+ * Lookup the address of the Interrupt Translation Table associated with
+ * a device ID and return the address of the ITTE belonging to the event ID
+ * (which is an index into that table).
+ */
+static paddr_t its_get_itte_address(struct virt_its *its,
+uint32_t devid, uint32_t evid)
+{
+paddr_t addr = get_baser_phys_addr(its->baser_dev);
+uint64_t itt;
+
+if ( devid >= its->max_devices )
+return INVALID_PADDR;
+
+if ( vgic_access_guest_memory(its->d, addr + devid * sizeof(uint64_t),
+  , sizeof(itt), false) )
+return INVALID_PADDR;
+
+if ( evid >= DEV_TABLE_ITT_SIZE(itt) ||
+ DEV_TABLE_ITT_ADDR(itt) == INVALID_PADDR )
+return INVALID_PADDR;
+
+return DEV_TABLE_ITT_ADDR(itt) + evid * sizeof(struct vits_itte);
+}
+
+/*
+ * Queries the collection and device tables to get the vCPU and virtual
+ * LPI number for a given guest event. This first accesses the guest memory
+ * to resolve the address of the ITTE, then reads the ITTE entry at this
+ * address and puts the result in vcpu_ptr and vlpi_ptr.
+ * Requires the ITS lock to be held.
+ */
+static bool read_itte_locked(struct virt_its *its, uint32_t devid,
+ uint32_t evid, struct vcpu **vcpu_ptr,
+ uint32_t *vlpi_ptr)
+{
+paddr_t addr;
+struct vits_itte itte;
+struct vcpu *vcpu;
+
+ASSERT(spin_is_locked(>its_lock));
+
+addr = its_get_itte_address(its, devid, evid);
+if ( addr == INVALID_PADDR )
+return false;
+
+if ( vgic_access_guest_memory(its->d, addr, , sizeof(itte), false) )
+

[Xen-devel] [PATCH v5 04/30] ARM: GICv3 ITS: initialize host ITS

2017-04-05 Thread Andre Przywara
Map the registers frame for each host ITS and populate the host ITS
structure with some parameters describing the size of certain properties
like the number of bits for device IDs.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c| 33 ++
 xen/arch/arm/gic-v3.c|  5 +
 xen/include/asm-arm/gic_v3_its.h | 44 
 3 files changed, 82 insertions(+)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 6b02349..0298866 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -19,8 +19,10 @@
  */
 
 #include 
+#include 
 #include 
 #include 
+#include 
 
 /*
  * No lock here, as this list gets only populated upon boot while scanning
@@ -33,6 +35,37 @@ bool gicv3_its_host_has_its(void)
 return !list_empty(_its_list);
 }
 
+static int gicv3_its_init_single_its(struct host_its *hw_its)
+{
+uint64_t reg;
+
+hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size);
+if ( !hw_its->its_base )
+return -ENOMEM;
+
+reg = readq_relaxed(hw_its->its_base + GITS_TYPER);
+hw_its->devid_bits = GITS_TYPER_DEVICE_ID_BITS(reg);
+hw_its->evid_bits = GITS_TYPER_EVENT_ID_BITS(reg);
+hw_its->itte_size = GITS_TYPER_ITT_SIZE(reg);
+
+return 0;
+}
+
+int gicv3_its_init(void)
+{
+struct host_its *hw_its;
+int ret;
+
+list_for_each_entry(hw_its, _its_list, entry)
+{
+ret = gicv3_its_init_single_its(hw_its);
+if ( ret )
+return ret;
+}
+
+return 0;
+}
+
 /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */
 void gicv3_its_dt_init(const struct dt_device_node *node)
 {
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index b626298..d3d5784 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1590,6 +1590,11 @@ static int __init gicv3_init(void)
 spin_lock();
 
 gicv3_dist_init();
+
+res = gicv3_its_init();
+if ( res )
+panic("GICv3: ITS: initialization failed: %d\n", res);
+
 res = gicv3_cpu_init();
 gicv3_hyp_init();
 
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index 765a655..7d88987 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -20,6 +20,38 @@
 #ifndef __ASM_ARM_ITS_H__
 #define __ASM_ARM_ITS_H__
 
+#define GITS_CTLR   0x000
+#define GITS_IIDR   0x004
+#define GITS_TYPER  0x008
+#define GITS_CBASER 0x080
+#define GITS_CWRITER0x088
+#define GITS_CREADR 0x090
+#define GITS_BASER_NR_REGS  8
+#define GITS_BASER0 0x100
+#define GITS_BASER1 0x108
+#define GITS_BASER2 0x110
+#define GITS_BASER3 0x118
+#define GITS_BASER4 0x120
+#define GITS_BASER5 0x128
+#define GITS_BASER6 0x130
+#define GITS_BASER7 0x138
+
+/* Register bits */
+#define GITS_TYPER_DEVIDS_SHIFT 13
+#define GITS_TYPER_DEVIDS_MASK  (0x1fUL << GITS_TYPER_DEVIDS_SHIFT)
+#define GITS_TYPER_DEVICE_ID_BITS(r)(((r & GITS_TYPER_DEVIDS_MASK) >> \
+   GITS_TYPER_DEVIDS_SHIFT) + 1)
+
+#define GITS_TYPER_IDBITS_SHIFT 8
+#define GITS_TYPER_IDBITS_MASK  (0x1fUL << GITS_TYPER_IDBITS_SHIFT)
+#define GITS_TYPER_EVENT_ID_BITS(r) (((r & GITS_TYPER_IDBITS_MASK) >> \
+   GITS_TYPER_IDBITS_SHIFT) + 1)
+
+#define GITS_TYPER_ITT_SIZE_SHIFT   4
+#define GITS_TYPER_ITT_SIZE_MASK(0xfUL << GITS_TYPER_ITT_SIZE_SHIFT)
+#define GITS_TYPER_ITT_SIZE(r)  r) & GITS_TYPER_ITT_SIZE_MASK) >> \
+ GITS_TYPER_ITT_SIZE_SHIFT) + 
1)
+
 #include 
 
 /* data structure for each hardware ITS */
@@ -28,6 +60,10 @@ struct host_its {
 const struct dt_device_node *dt_node;
 paddr_t addr;
 paddr_t size;
+void __iomem *its_base;
+unsigned int devid_bits;
+unsigned int evid_bits;
+unsigned int itte_size;
 };
 
 
@@ -40,6 +76,9 @@ void gicv3_its_dt_init(const struct dt_device_node *node);
 
 bool gicv3_its_host_has_its(void);
 
+/* Initialize the host structures for the host ITSes. */
+int gicv3_its_init(void);
+
 #else
 
 static LIST_HEAD(host_its_list);
@@ -53,6 +92,11 @@ static inline bool gicv3_its_host_has_its(void)
 return false;
 }
 
+static inline int gicv3_its_init(void)
+{
+return 0;
+}
+
 #endif /* CONFIG_HAS_ITS */
 
 #endif
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 00/30] arm64: Dom0 ITS emulation

2017-04-05 Thread Andre Przywara
Hi,

another round with lots of fixes for the ITS emulation series.
The access to guest memory has been reworked, we now use a routine to
copy to and from guest memory to also guarantee atomic access.
This is courtesy of Vijaya Kumar, from a previous series.
For a detailed changelog see below.

Open questions:
- Do we really need the GENMASK_ULL and BIT_ULL version ? This series is
  really only for ARM64 (which doesn't need those), so we could get rid
  of this, possibly introduce them later should we *really* need an ARM32
  version. I think this will be our least problem then.
- I was thinking about MOVALL and the spec is really confusing here.
  It needs some discussion whether we need to emulate it or not. However
  Linux does not use this command, so we might get away with it now.
  An implementation might be doable along the lines of INVALL.
- Julien asked for more ITS documentation, which is quite hard to come up
  with. I will try to explain things in more details tomorrow in commit
  messages, if there are still things missing.

Cheers,
Andre

--
This series adds support for emulation of an ARM GICv3 ITS interrupt
controller. For hardware which relies on the ITS to provide interrupts for
its peripherals this code is needed to get a machine booted into Dom0 at
all. ITS emulation for DomUs is only really useful with PCI passthrough,
which is not yet available for ARM. It is expected that this feature
will be co-developed with the ITS DomU code. However this code drop here
considered DomU emulation already, to keep later architectural changes
to a minimum.

Some generic design principles:

* The current GIC code statically allocates structures for each supported
IRQ (both for the host and the guest), which due to the potentially
millions of LPI interrupts is not feasible to copy for the ITS.
So we refrain from introducing the ITS as a first class Xen interrupt
controller, also we don't hold struct irq_desc's or struct pending_irq's
for each possible LPI.
Fortunately LPIs are only interesting to guests, so we get away with
storing only the virtual IRQ number and the guest VCPU for each allocated
host LPI, which can be stashed into one uint64_t. This data is stored in
a two-level table, which is both memory efficient and quick to access.
We hook into the existing IRQ handling and VGIC code to avoid accessing
the normal structures, providing alternative methods for getting the
needed information (priority, is enabled?) for LPIs.
For interrupts which are queued to or are actually in a guest we
allocate struct pending_irq's on demand. As it is expected that only a
very small number of interrupts is ever on a VCPU at the same time, this
seems like the best approach. For now allocated structs are re-used and
held in a linked list. Should it emerge that traversing a linked list
is a performance issue, this can be changed to use a hash table.

* On the guest side we (later will) have to deal with malicious guests
trying to hog Xen with mapping requests for a lot of LPIs, for instance.
As the ITS actually uses system memory for storing status information,
we use this memory (which the guest has to provide) to naturally limit
a guest. We use a function to copy parts of the guest memory to be able
to access those tables.
As ITS commands in need to iterate those tables are pretty rare after all,
we for now map them on demand upon emulating a virtual ITS command. This is
acceptable because "mapping" them is actually very cheap on arm64. Also as
we can't properly protect those areas due to their sub-page-size property,
we validate the data in there before actually using it. The vITS code
basically just stores the data in there which the guest has actually
transferred via the virtual ITS command queue before, so there is no secret
revealed nor does it create an attack vector for a malicious guest.

* An obvious approach to handling some guest ITS commands would be to
propagate them to the host, for instance to map devices and LPIs and
to enable or disable LPIs.
However this (later with DomU support) will create an attack vector, as
a malicious guest could try to fill the host command queue with
propagated commands.
So we try to avoid this situation: Dom0 sending a device mapping (MAPD)
command is the only time we allow queuing commands to the host ITS command
queue, as this seems to be the only reliable way of getting the
required information at the moment. However at the same time we map all
events to LPIs already, also enable them. This avoids sending commands
later at runtime, as we can deal with mappings and LPI enabling/disabling
internally.

As it is expected that the ITS support will become a tech preview in the
first release, there is a Kconfig option to enable it. Also it is
supported on arm64 only, which will most likely not change in the future.
This leads to some hideous constructs like an #ifdef'ed header file with
empty function stubs, I have some hope we can still 

[Xen-devel] [PATCH v5 06/30] ARM: GICv3 ITS: allocate device and collection table

2017-04-05 Thread Andre Przywara
Each ITS maps a pair of a DeviceID (for instance derived from a PCI
b/d/f triplet) and an EventID (the MSI payload or interrupt ID) to a
pair of LPI number and collection ID, which points to the target CPU.
This mapping is stored in the device and collection tables, which software
has to provide for the ITS to use.
Allocate the required memory and hand it over to the ITS.

Signed-off-by: Andre Przywara 
Reviewed-by: Stefano Stabellini 
---
 xen/arch/arm/gic-v3-its.c| 132 +++
 xen/include/asm-arm/gic_v3_its.h |  32 ++
 2 files changed, 164 insertions(+)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 0298866..eef2933 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -35,9 +35,109 @@ bool gicv3_its_host_has_its(void)
 return !list_empty(_its_list);
 }
 
+#define BASER_ATTR_MASK   \
+((0x3UL << GITS_BASER_SHAREABILITY_SHIFT)   | \
+ (0x7UL << GITS_BASER_OUTER_CACHEABILITY_SHIFT) | \
+ (0x7UL << GITS_BASER_INNER_CACHEABILITY_SHIFT))
+#define BASER_RO_MASK   (GENMASK_ULL(58, 56) | GENMASK_ULL(52, 48))
+
+/* Check that the physical address can be encoded in the PROPBASER register. */
+static bool check_baser_phys_addr(void *vaddr, unsigned int page_bits)
+{
+paddr_t paddr = virt_to_maddr(vaddr);
+
+return (!(paddr & ~GENMASK_ULL(page_bits < 16 ? 47 : 51, page_bits)));
+}
+
+static uint64_t encode_baser_phys_addr(paddr_t addr, unsigned int page_bits)
+{
+uint64_t ret = addr & GENMASK_ULL(47, page_bits);
+
+if ( page_bits < 16 )
+return ret;
+
+/* For 64K pages address bits 51-48 are encoded in bits 15-12. */
+return ret | ((addr & GENMASK_ULL(51, 48)) >> (48 - 12));
+}
+
+/* The ITS BASE registers work with page sizes of 4K, 16K or 64K. */
+#define BASER_PAGE_BITS(sz) ((sz) * 2 + 12)
+
+static int its_map_baser(void __iomem *basereg, uint64_t regc,
+ unsigned int nr_items)
+{
+uint64_t attr, reg;
+unsigned int entry_size = GITS_BASER_ENTRY_SIZE(regc);
+unsigned int pagesz = 2;/* try 64K pages first, then go down. */
+unsigned int table_size;
+void *buffer;
+
+attr  = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT;
+attr |= GIC_BASER_CACHE_SameAsInner << GITS_BASER_OUTER_CACHEABILITY_SHIFT;
+attr |= GIC_BASER_CACHE_RaWaWb << GITS_BASER_INNER_CACHEABILITY_SHIFT;
+
+/*
+ * Setup the BASE register with the attributes that we like. Then read
+ * it back and see what sticks (page size, cacheability and shareability
+ * attributes), retrying if necessary.
+ */
+retry:
+table_size = ROUNDUP(nr_items * entry_size, BIT(BASER_PAGE_BITS(pagesz)));
+/* The BASE registers support at most 256 pages. */
+table_size = min(table_size, 256U << BASER_PAGE_BITS(pagesz));
+
+buffer = _xzalloc(table_size, BIT(BASER_PAGE_BITS(pagesz)));
+if ( !buffer )
+return -ENOMEM;
+
+if ( !check_baser_phys_addr(buffer, BASER_PAGE_BITS(pagesz)) )
+{
+xfree(buffer);
+return -ERANGE;
+}
+
+reg  = attr;
+reg |= (pagesz << GITS_BASER_PAGE_SIZE_SHIFT);
+reg |= (table_size >> BASER_PAGE_BITS(pagesz)) - 1;
+reg |= regc & BASER_RO_MASK;
+reg |= GITS_VALID_BIT;
+reg |= encode_baser_phys_addr(virt_to_maddr(buffer),
+  BASER_PAGE_BITS(pagesz));
+
+writeq_relaxed(reg, basereg);
+regc = readq_relaxed(basereg);
+
+/* The host didn't like our attributes, just use what it returned. */
+if ( (regc & BASER_ATTR_MASK) != attr )
+{
+/* If we can't map it shareable, drop cacheability as well. */
+if ( (regc & GITS_BASER_SHAREABILITY_MASK) == GIC_BASER_NonShareable )
+{
+regc &= ~GITS_BASER_INNER_CACHEABILITY_MASK;
+writeq_relaxed(regc, basereg);
+}
+attr = regc & BASER_ATTR_MASK;
+}
+if ( (regc & GITS_BASER_INNER_CACHEABILITY_MASK) <= GIC_BASER_CACHE_nC )
+clean_and_invalidate_dcache_va_range(buffer, table_size);
+
+/* If the host accepted our page size, we are done. */
+if ( ((regc >> GITS_BASER_PAGE_SIZE_SHIFT) & 0x3UL) == pagesz )
+return 0;
+
+xfree(buffer);
+
+if ( pagesz-- > 0 )
+goto retry;
+
+/* None of the page sizes was accepted, give up */
+return -EINVAL;
+}
+
 static int gicv3_its_init_single_its(struct host_its *hw_its)
 {
 uint64_t reg;
+int i, ret;
 
 hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size);
 if ( !hw_its->its_base )
@@ -48,6 +148,38 @@ static int gicv3_its_init_single_its(struct host_its 
*hw_its)
 hw_its->evid_bits = GITS_TYPER_EVENT_ID_BITS(reg);
 hw_its->itte_size = GITS_TYPER_ITT_SIZE(reg);
 
+for ( i = 0; i < GITS_BASER_NR_REGS; i++ )
+{
+void __iomem *basereg = hw_its->its_base + 

[Xen-devel] [PATCH v5 16/30] ARM: vGICv3: handle disabled LPIs

2017-04-05 Thread Andre Przywara
If a guest disables an LPI, we do not forward this to the associated
host LPI to avoid queueing commands to the host ITS command queue.
So it may happen that an LPI fires nevertheless on the host. In this
case we can bail out early, but have to save the pending state on the
virtual side. We do this by storing the pending bit in struct
pending_irq, which is assiociated with mapped LPIs.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-lpi.c | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
index d8baebc..7d20986 100644
--- a/xen/arch/arm/gic-v3-lpi.c
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -136,6 +136,22 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool 
use_pta)
 return per_cpu(lpi_redist, cpu).redist_id << 16;
 }
 
+static bool vgic_can_inject_lpi(struct vcpu *vcpu, uint32_t vlpi)
+{
+struct pending_irq *p;
+
+p = vcpu->domain->arch.vgic.handler->lpi_to_pending(vcpu->domain, vlpi);
+if ( !p )
+return false;
+
+if ( test_bit(GIC_IRQ_GUEST_ENABLED, >status) )
+return true;
+
+set_bit(GIC_IRQ_GUEST_LPI_PENDING, >status);
+
+return false;
+}
+
 /*
  * Handle incoming LPIs, which are a bit special, because they are potentially
  * numerous and also only get injected into guests. Treat them specially here,
@@ -187,7 +203,15 @@ void gicv3_do_LPI(unsigned int lpi)
 
 /* Check if the VCPU is ready to receive LPIs. */
 if ( vcpu->arch.vgic.flags & VGIC_V3_LPIS_ENABLED )
-vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
+{
+/*
+ * We keep all host LPIs enabled, so check if it's disabled on the
+ * guest side and just record this LPI in the virtual pending table
+ * in this case. The guest picks it up once it gets enabled again.
+ */
+if ( vgic_can_inject_lpi(vcpu, hlpi.virt_lpi) )
+vgic_vcpu_inject_irq(vcpu, hlpi.virt_lpi);
+}
 
 rcu_unlock_domain(d);
 }
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 23/30] ARM: vITS: handle MAPTI command

2017-04-05 Thread Andre Przywara
The MAPTI commands associates a DeviceID/EventID pair with a LPI/CPU
pair and actually instantiates LPI interrupts.
We connect the already allocated host LPI to this virtual LPI, so that
any triggering LPI on the host can be quickly forwarded to a guest.
Beside entering the VCPU and the virtual LPI number in the respective
host LPI entry, we also initialize and add the already allocated
struct pending_irq to our radix tree, so that we can now easily find it
by its virtual LPI number.
To be able to later find the targetting VCPU for any given LPI without
having to walk *all* ITS tables, we store the VCPU ID in the pending_irq
struct as well.
This exports the vgic_init_pending_irq() function to be able to
initialize a new struct pending_irq.
As write_itte() is now eventually used, we can now add the static tag.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c| 74 ++
 xen/arch/arm/gic-v3-lpi.c| 18 ++
 xen/arch/arm/vgic-v3-its.c   | 76 ++--
 xen/arch/arm/vgic.c  |  2 +-
 xen/include/asm-arm/gic_v3_its.h |  6 
 xen/include/asm-arm/vgic.h   |  2 ++
 6 files changed, 175 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 76b0316..d970119 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -777,6 +777,80 @@ out:
 return ret;
 }
 
+/* Must be called with the its_device_lock held. */
+static struct its_devices *get_its_device(struct domain *d, paddr_t vdoorbell,
+  uint32_t vdevid)
+{
+struct rb_node *node = d->arch.vgic.its_devices.rb_node;
+struct its_devices *dev;
+
+ASSERT(spin_is_locked(>arch.vgic.its_devices_lock));
+
+while (node)
+{
+int cmp;
+
+dev = rb_entry(node, struct its_devices, rbnode);
+cmp = compare_its_guest_devices(dev, vdoorbell, vdevid);
+
+if ( !cmp )
+return dev;
+
+if ( cmp > 0 )
+node = node->rb_left;
+else
+node = node->rb_right;
+}
+
+return NULL;
+}
+
+static uint32_t get_host_lpi(struct its_devices *dev, uint32_t eventid)
+{
+uint32_t host_lpi = 0;
+
+if ( dev && (eventid < dev->eventids) )
+host_lpi = dev->host_lpi_blocks[eventid / LPI_BLOCK] +
+   (eventid % LPI_BLOCK);
+
+return host_lpi;
+}
+
+/*
+ * Connects the event ID for an already assigned device to the given VCPU/vLPI
+ * pair. The corresponding physical LPI is already mapped on the host side
+ * (when assigning the physical device to the guest), so we just connect the
+ * target VCPU/vLPI pair to that interrupt to inject it properly if it fires.
+ * Returns a pointer to the already allocated struct pending_irq that is
+ * meant to be used by that event.
+ */
+struct pending_irq *gicv3_assign_guest_event(struct domain *d,
+ paddr_t vdoorbell_address,
+ uint32_t vdevid, uint32_t 
veventid,
+ struct vcpu *v, uint32_t virt_lpi)
+{
+struct its_devices *dev;
+struct pending_irq *pirq = NULL;
+uint32_t host_lpi = 0;
+
+spin_lock(>arch.vgic.its_devices_lock);
+dev = get_its_device(d, vdoorbell_address, vdevid);
+if ( dev )
+{
+host_lpi = get_host_lpi(dev, veventid);
+pirq = >pend_irqs[veventid];
+}
+spin_unlock(>arch.vgic.its_devices_lock);
+
+if ( !host_lpi || !pirq )
+return NULL;
+
+gicv3_lpi_update_host_entry(host_lpi, d->domain_id,
+v ? v->vcpu_id : INVALID_VCPU_ID, virt_lpi);
+
+return pirq;
+}
+
 /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */
 void gicv3_its_dt_init(const struct dt_device_node *node)
 {
diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
index 7d20986..c997ed5 100644
--- a/xen/arch/arm/gic-v3-lpi.c
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -216,6 +216,24 @@ void gicv3_do_LPI(unsigned int lpi)
 rcu_unlock_domain(d);
 }
 
+void gicv3_lpi_update_host_entry(uint32_t host_lpi, int domain_id,
+ unsigned int vcpu_id, uint32_t virt_lpi)
+{
+union host_lpi *hlpip, hlpi;
+
+ASSERT(host_lpi >= LPI_OFFSET);
+
+host_lpi -= LPI_OFFSET;
+
+hlpip = _data.host_lpis[host_lpi / HOST_LPIS_PER_PAGE][host_lpi % 
HOST_LPIS_PER_PAGE];
+
+hlpi.virt_lpi = virt_lpi;
+hlpi.dom_id = domain_id;
+hlpi.vcpu_id = vcpu_id;
+
+write_u64_atomic(>data, hlpi.data);
+}
+
 static int gicv3_lpi_allocate_pendtable(uint64_t *reg)
 {
 uint64_t val;
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 0372ed0..079dd44 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -275,8 +275,8 @@ static bool write_itte_locked(struct 

[Xen-devel] [PATCH v5 21/30] ARM: vITS: handle MAPC command

2017-04-05 Thread Andre Przywara
The MAPC command associates a given collection ID with a given
redistributor, thus mapping collections to VCPUs.
We just store the vcpu_id in the collection table for that.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 36f942a..bbca5cf 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -95,6 +95,21 @@ static paddr_t get_baser_phys_addr(uint64_t reg)
 }
 
 /* Must be called with the ITS lock held. */
+static int its_set_collection(struct virt_its *its, uint16_t collid,
+  uint16_t vcpu_id)
+{
+paddr_t addr = get_baser_phys_addr(its->baser_coll);
+
+ASSERT(spin_is_locked(>its_lock));
+
+if ( collid >= its->max_collections )
+return -ENOENT;
+
+return vgic_access_guest_memory(its->d, addr + collid * sizeof(uint16_t),
+_id, sizeof(vcpu_id), true);
+}
+
+/* Must be called with the ITS lock held. */
 static struct vcpu *get_vcpu_from_collection(struct virt_its *its,
  uint16_t collid)
 {
@@ -346,6 +361,29 @@ static int its_handle_int(struct virt_its *its, uint64_t 
*cmdptr)
 return 0;
 }
 
+static int its_handle_mapc(struct virt_its *its, uint64_t *cmdptr)
+{
+uint32_t collid = its_cmd_get_collection(cmdptr);
+uint64_t rdbase = its_cmd_mask_field(cmdptr, 2, 16, 44);
+
+if ( collid >= its->max_collections )
+return -1;
+
+if ( rdbase >= its->d->max_vcpus )
+return -1;
+
+spin_lock(>its_lock);
+
+if ( its_cmd_get_validbit(cmdptr) )
+its_set_collection(its, collid, rdbase);
+else
+its_set_collection(its, collid, UNMAPPED_COLLECTION);
+
+spin_unlock(>its_lock);
+
+return 0;
+}
+
 #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
 
 /*
@@ -380,6 +418,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 case GITS_CMD_INT:
 ret = its_handle_int(its, command);
 break;
+case GITS_CMD_MAPC:
+ret = its_handle_mapc(its, command);
+break;
 case GITS_CMD_SYNC:
 /* We handle ITS commands synchronously, so we ignore SYNC. */
 break;
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 01/30] bitops: add GENMASK_ULL

2017-04-05 Thread Andre Przywara
To safely handle 64-bit registers even on 32-bit systems, introduce
a GENMASK_ULL variant (lifted from Linux).
This adds a BITS_PER_LONG_LONG define as well.
Also fix a bug in the comment for the existing GENMASK variant.

Signed-off-by: Andre Przywara 
---
 xen/include/asm-arm/config.h | 2 ++
 xen/include/xen/bitops.h | 5 -
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index b2edf95..1f730ce 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -19,6 +19,8 @@
 #define BITS_PER_LONG (BYTES_PER_LONG << 3)
 #define POINTER_ALIGN BYTES_PER_LONG
 
+#define BITS_PER_LONG_LONG (sizeof (long long) * BITS_PER_BYTE)
+
 /* xen_ulong_t is always 64 bits */
 #define BITS_PER_XEN_ULONG 64
 
diff --git a/xen/include/xen/bitops.h b/xen/include/xen/bitops.h
index bd0883a..9261e06 100644
--- a/xen/include/xen/bitops.h
+++ b/xen/include/xen/bitops.h
@@ -5,11 +5,14 @@
 /*
  * Create a contiguous bitmask starting at bit position @l and ending at
  * position @h. For example
- * GENMASK(30, 21) gives us the 32bit vector 0x01fe0.
+ * GENMASK(30, 21) gives us the 32bit vector 0x7fe0.
  */
 #define GENMASK(h, l) \
 (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h
 
+#define GENMASK_ULL(h, l) \
+(((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h
+
 /*
  * ffs: find first bit set. This is defined the same way as
  * the libc and compiler builtin ffs routines, therefore
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 29/30] ARM: vITS: create ITS subnodes for Dom0 DT

2017-04-05 Thread Andre Przywara
Dom0 expects all ITSes in the system to be propagated to be able to
use MSIs.
Create Dom0 DT nodes for each hardware ITS, keeping the register frame
address the same, as the doorbell address that the Dom0 drivers program
into the BARs has to match the hardware.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c| 78 
 xen/arch/arm/gic-v3.c|  4 ++-
 xen/include/asm-arm/gic_v3_its.h | 13 +++
 3 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index a57e63a..a167471 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -20,6 +20,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -875,6 +876,83 @@ int gicv3_lpi_change_vcpu(struct domain *d, paddr_t 
vdoorbell,
 return 0;
 }
 
+/*
+ * Create the respective guest DT nodes for a list of host ITSes.
+ * This copies the reg property, so the guest sees the ITS at the same address
+ * as the host.
+ * Giving NULL for the its_list will make it use the list of host ITSes.
+ */
+int gicv3_its_make_dt_nodes(struct list_head *its_list,
+const struct domain *d,
+const struct dt_device_node *gic,
+void *fdt)
+{
+uint32_t len;
+int res;
+const void *prop = NULL;
+const struct dt_device_node *its = NULL;
+const struct host_its *its_data;
+
+if ( !its_list )
+its_list = _its_list;
+
+if ( list_empty(its_list) )
+return 0;
+
+/* The sub-nodes require the ranges property */
+prop = dt_get_property(gic, "ranges", );
+if ( !prop )
+{
+printk(XENLOG_ERR "Can't find ranges property for the gic node\n");
+return -FDT_ERR_XEN(ENOENT);
+}
+
+res = fdt_property(fdt, "ranges", prop, len);
+if ( res )
+return res;
+
+list_for_each_entry(its_data, its_list, entry)
+{
+its = its_data->dt_node;
+
+res = fdt_begin_node(fdt, its->name);
+if ( res )
+return res;
+
+res = fdt_property_string(fdt, "compatible", "arm,gic-v3-its");
+if ( res )
+return res;
+
+res = fdt_property(fdt, "msi-controller", NULL, 0);
+if ( res )
+return res;
+
+if ( its->phandle )
+{
+res = fdt_property_cell(fdt, "phandle", its->phandle);
+if ( res )
+return res;
+}
+
+/* Use the same reg regions as the ITS node in host DTB. */
+prop = dt_get_property(its, "reg", );
+if ( !prop )
+{
+printk(XENLOG_ERR "GICv3: Can't find ITS reg property.\n");
+res = -FDT_ERR_XEN(ENOENT);
+return res;
+}
+
+res = fdt_property(fdt, "reg", prop, len);
+if ( res )
+return res;
+
+fdt_end_node(fdt);
+}
+
+return res;
+}
+
 /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */
 void gicv3_its_dt_init(const struct dt_device_node *node)
 {
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 54fbb19..2fbcf52 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -1172,8 +1172,10 @@ static int gicv3_make_hwdom_dt_node(const struct domain 
*d,
 
 res = fdt_property(fdt, "reg", new_cells, len);
 xfree(new_cells);
+if ( res )
+return res;
 
-return res;
+return gicv3_its_make_dt_nodes(NULL, d, gic, fdt);
 }
 
 static const hw_irq_controller gicv3_host_irq_type = {
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index 1b8e47c..6538916 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -165,6 +165,12 @@ void vgic_v3_its_free_domain(struct domain *d);
 int vgic_v3_its_init_virtual(struct domain *d, paddr_t guest_addr,
 unsigned int devid_bits, unsigned int intid_bits);
 
+/* Given a list of ITSes, create the appropriate DT nodes for a domain. */
+int gicv3_its_make_dt_nodes(struct list_head *its_list,
+const struct domain *d,
+const struct dt_device_node *gic,
+void *fdt);
+
 /*
  * Map a device on the host by allocating an ITT on the host (ITS).
  * "nr_event" specifies how many events (interrupts) this device will need.
@@ -248,6 +254,13 @@ static inline int vgic_v3_its_init_virtual(struct domain 
*d,
 {
 return 0;
 }
+static inline int gicv3_its_make_dt_nodes(struct list_head *its_list,
+   const struct domain *d,
+   const struct dt_device_node *gic,
+   void *fdt)
+{
+return 0;
+}
 
 #endif /* CONFIG_HAS_ITS */
 
-- 
2.8.2


___
Xen-devel mailing list

[Xen-devel] [PATCH v5 09/30] ARM: GICv3 ITS: introduce host LPI array

2017-04-05 Thread Andre Przywara
The number of LPIs on a host can be potentially huge (millions),
although in practise will be mostly reasonable. So prematurely allocating
an array of struct irq_desc's for each LPI is not an option.
However Xen itself does not care about LPIs, as every LPI will be injected
into a guest (Dom0 for now).
Create a dense data structure (8 Bytes) for each LPI which holds just
enough information to determine the virtual IRQ number and the VCPU into
which the LPI needs to be injected.
Also to not artificially limit the number of LPIs, we create a 2-level
table for holding those structures.
This patch introduces functions to initialize these tables and to
create, lookup and destroy entries for a given LPI.
By using the naturally atomic access guarantee the native uint64_t data
type gives us, we allocate and access LPI information in a way that does
not require a lock.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c|  60 +++
 xen/arch/arm/gic-v3-lpi.c| 227 +++
 xen/include/asm-arm/gic_v3_its.h |   6 ++
 xen/include/asm-arm/irq.h|   8 ++
 4 files changed, 301 insertions(+)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 1ecd63b..eb47c9d 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -157,6 +157,20 @@ static int its_send_cmd_sync(struct host_its *its, 
unsigned int cpu)
 return its_send_command(its, cmd);
 }
 
+static int its_send_cmd_mapti(struct host_its *its,
+  uint32_t deviceid, uint32_t eventid,
+  uint32_t pintid, uint16_t icid)
+{
+uint64_t cmd[4];
+
+cmd[0] = GITS_CMD_MAPTI | ((uint64_t)deviceid << 32);
+cmd[1] = eventid | ((uint64_t)pintid << 32);
+cmd[2] = icid;
+cmd[3] = 0x00;
+
+return its_send_command(its, cmd);
+}
+
 static int its_send_cmd_mapc(struct host_its *its, uint32_t collection_id,
  unsigned int cpu)
 {
@@ -171,6 +185,19 @@ static int its_send_cmd_mapc(struct host_its *its, 
uint32_t collection_id,
 return its_send_command(its, cmd);
 }
 
+static int its_send_cmd_inv(struct host_its *its,
+uint32_t deviceid, uint32_t eventid)
+{
+uint64_t cmd[4];
+
+cmd[0] = GITS_CMD_INV | ((uint64_t)deviceid << 32);
+cmd[1] = eventid;
+cmd[2] = 0x00;
+cmd[3] = 0x00;
+
+return its_send_command(its, cmd);
+}
+
 /* Set up the (1:1) collection mapping for the given host CPU. */
 int gicv3_its_setup_collection(unsigned int cpu)
 {
@@ -450,6 +477,39 @@ int gicv3_its_init(void)
 return 0;
 }
 
+/*
+ * On the host ITS @its, map @nr_events consecutive LPIs.
+ * The mapping connects a device @devid and event @eventid pair to LPI @lpi,
+ * increasing both @eventid and @lpi to cover the number of requested LPIs.
+ */
+static int gicv3_its_map_host_events(struct host_its *its,
+ uint32_t devid, uint32_t eventid,
+ uint32_t lpi, uint32_t nr_events)
+{
+uint32_t i;
+int ret;
+
+for ( i = 0; i < nr_events; i++ )
+{
+/* For now we map every host LPI to host CPU 0 */
+ret = its_send_cmd_mapti(its, devid, eventid + i, lpi + i, 0);
+if ( ret )
+return ret;
+
+ret = its_send_cmd_inv(its, devid, eventid + i);
+if ( ret )
+return ret;
+}
+
+/* TODO: Consider using INVALL here. Didn't work on the model, though. */
+
+ret = its_send_cmd_sync(its, 0);
+if ( ret )
+return ret;
+
+return gicv3_its_wait_commands(its);
+}
+
 /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */
 void gicv3_its_dt_init(const struct dt_device_node *node)
 {
diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
index 9d3df7f..0785701 100644
--- a/xen/arch/arm/gic-v3-lpi.c
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -20,14 +20,37 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 
+/*
+ * There could be a lot of LPIs on the host side, and they always go to
+ * a guest. So having a struct irq_desc for each of them would be wasteful
+ * and useless.
+ * Instead just store enough information to find the right VCPU to inject
+ * those LPIs into, which just requires the virtual LPI number.
+ * To avoid a global lock on this data structure, this is using a lockless
+ * approach relying on the architectural atomicity of native data types:
+ * We read or write the "data" view of this union atomically, then can
+ * access the broken-down fields in our local copy.
+ */
+union host_lpi {
+uint64_t data;
+struct {
+uint32_t virt_lpi;
+uint16_t dom_id;
+uint16_t vcpu_id;
+};
+};
+
 #define LPI_PROPTABLE_NEEDS_FLUSHING(1U << 0)
 
 /* Global state */
@@ -35,12 +58,23 @@ static struct {
 /* The global LPI property 

[Xen-devel] [PATCH v5 12/30] ARM: GICv3: introduce separate pending_irq structs for LPIs

2017-04-05 Thread Andre Przywara
For the same reason that allocating a struct irq_desc for each
possible LPI is not an option, having a struct pending_irq for each LPI
is also not feasible. We only care about mapped LPIs, so we can get away
with having struct pending_irq's only for them.
Maintain a radix tree per domain where we drop the pointer to the
respective pending_irq. The index used is the virtual LPI number.
The memory for the actual structures has been allocated already per
device at device mapping time.
Teach the existing VGIC functions to find the right pointer when being
given a virtual LPI number.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v2.c   |  8 
 xen/arch/arm/vgic-v3.c   | 22 ++
 xen/arch/arm/vgic.c  |  2 ++
 xen/include/asm-arm/domain.h |  2 ++
 xen/include/asm-arm/vgic.h   |  2 ++
 5 files changed, 36 insertions(+)

diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 0674f7b..3cad68f 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -703,10 +703,18 @@ static void vgic_v2_domain_free(struct domain *d)
 /* Nothing to be cleanup for this driver */
 }
 
+static struct pending_irq *vgic_v2_lpi_to_pending(struct domain *d,
+  unsigned int vlpi)
+{
+/* Dummy function, no LPIs on a VGICv2. */
+BUG();
+}
+
 static const struct vgic_ops vgic_v2_ops = {
 .vcpu_init   = vgic_v2_vcpu_init,
 .domain_init = vgic_v2_domain_init,
 .domain_free = vgic_v2_domain_free,
+.lpi_to_pending = vgic_v2_lpi_to_pending,
 .max_vcpus = 8,
 };
 
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 142eb64..5128f13 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -1451,6 +1451,9 @@ static int vgic_v3_domain_init(struct domain *d)
 
 vgic_v3_its_init_domain(d);
 
+rwlock_init(>arch.vgic.pend_lpi_tree_lock);
+radix_tree_init(>arch.vgic.pend_lpi_tree);
+
 /*
  * Domain 0 gets the hardware address.
  * Guests get the virtual platform layout.
@@ -1524,14 +1527,33 @@ static int vgic_v3_domain_init(struct domain *d)
 static void vgic_v3_domain_free(struct domain *d)
 {
 vgic_v3_its_free_domain(d);
+radix_tree_destroy(>arch.vgic.pend_lpi_tree, NULL);
 xfree(d->arch.vgic.rdist_regions);
 }
 
+/*
+ * Looks up a virtual LPI number in our tree of mapped LPIs. This will return
+ * the corresponding struct pending_irq, which we also use to store the
+ * enabled and pending bit plus the priority.
+ * Returns NULL if an LPI cannot be found (or no LPIs are supported).
+ */
+struct pending_irq *vgic_v3_lpi_to_pending(struct domain *d, unsigned int lpi)
+{
+struct pending_irq *pirq;
+
+read_lock(>arch.vgic.pend_lpi_tree_lock);
+pirq = radix_tree_lookup(>arch.vgic.pend_lpi_tree, lpi);
+read_unlock(>arch.vgic.pend_lpi_tree_lock);
+
+return pirq;
+}
+
 static const struct vgic_ops v3_ops = {
 .vcpu_init   = vgic_v3_vcpu_init,
 .domain_init = vgic_v3_domain_init,
 .domain_free = vgic_v3_domain_free,
 .emulate_reg  = vgic_v3_emulate_reg,
+.lpi_to_pending = vgic_v3_lpi_to_pending,
 /*
  * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU
  * that can be supported is up to 4096(==256*16) in theory.
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 67d75a6..d704d7c 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -435,6 +435,8 @@ struct pending_irq *irq_to_pending(struct vcpu *v, unsigned 
int irq)
  * are used for SPIs; the rests are used for per cpu irqs */
 if ( irq < 32 )
 n = >arch.vgic.pending_irqs[irq];
+else if ( is_lpi(irq) )
+n = v->domain->arch.vgic.handler->lpi_to_pending(v->domain, irq);
 else
 n = >domain->arch.vgic.pending_irqs[irq - 32];
 return n;
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 503a3cf..6ee7538 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -111,6 +111,8 @@ struct arch_domain
 uint32_t rdist_stride;  /* Re-Distributor stride */
 struct rb_root its_devices; /* Devices mapped to an ITS */
 spinlock_t its_devices_lock;/* Protects the its_devices tree */
+struct radix_tree_root pend_lpi_tree; /* Stores struct pending_irq's */
+rwlock_t pend_lpi_tree_lock;/* Protects the pend_lpi_tree */
 #endif
 } vgic;
 
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 894c3f1..7c86f5b 100644
--- a/xen/include/asm-arm/vgic.h
+++ b/xen/include/asm-arm/vgic.h
@@ -134,6 +134,8 @@ struct vgic_ops {
 void (*domain_free)(struct domain *d);
 /* vGIC sysreg/cpregs emulate */
 bool (*emulate_reg)(struct cpu_user_regs *regs, union hsr hsr);
+/* lookup the struct pending_irq for a given LPI interrupt */
+struct pending_irq *(*lpi_to_pending)(struct domain *d, unsigned int vlpi);
 /* 

[Xen-devel] [PATCH v5 17/30] ARM: vITS: add command handling stub and MMIO emulation

2017-04-05 Thread Andre Przywara
Emulate the memory mapped ITS registers and provide a stub to introduce
the ITS command handling framework (but without actually emulating any
commands at this time).

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c| 416 ++
 xen/arch/arm/vgic-v3.c|   9 -
 xen/include/asm-arm/gic_v3_defs.h |   9 +
 xen/include/asm-arm/gic_v3_its.h  |   3 +
 4 files changed, 428 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 9dfda59..f6bf1ee 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -78,6 +78,422 @@ void vgic_v3_its_free_domain(struct domain *d)
 ASSERT(RB_EMPTY_ROOT(>arch.vgic.its_devices));
 }
 
+/**
+ * Functions that handle ITS commands *
+ **/
+
+static uint64_t its_cmd_mask_field(uint64_t *its_cmd, unsigned int word,
+   unsigned int shift, unsigned int size)
+{
+return (le64_to_cpu(its_cmd[word]) >> shift) & (BIT(size) - 1);
+}
+
+#define its_cmd_get_command(cmd)its_cmd_mask_field(cmd, 0,  0,  8)
+#define its_cmd_get_deviceid(cmd)   its_cmd_mask_field(cmd, 0, 32, 32)
+#define its_cmd_get_size(cmd)   its_cmd_mask_field(cmd, 1,  0,  5)
+#define its_cmd_get_id(cmd) its_cmd_mask_field(cmd, 1,  0, 32)
+#define its_cmd_get_physical_id(cmd)its_cmd_mask_field(cmd, 1, 32, 32)
+#define its_cmd_get_collection(cmd) its_cmd_mask_field(cmd, 2,  0, 16)
+#define its_cmd_get_target_addr(cmd)its_cmd_mask_field(cmd, 2, 16, 32)
+#define its_cmd_get_validbit(cmd)   its_cmd_mask_field(cmd, 2, 63,  1)
+#define its_cmd_get_ittaddr(cmd)(its_cmd_mask_field(cmd, 2, 8, 44) << 
8)
+
+#define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
+
+/*
+ * Requires the vcmd_lock to be held.
+ * TODO: Investigate whether we can be smarter here and don't need to hold
+ * the lock all of the time.
+ */
+static int vgic_its_handle_cmds(struct domain *d, struct virt_its *its)
+{
+paddr_t addr = its->cbaser & GENMASK_ULL(51, 12);
+uint64_t command[4];
+
+ASSERT(spin_is_locked(>vcmd_lock));
+
+if ( its->cwriter >= ITS_CMD_BUFFER_SIZE(its->cbaser) )
+return -1;
+
+while ( its->creadr != its->cwriter )
+{
+int ret;
+
+ret = vgic_access_guest_memory(d, addr + its->creadr,
+   command, sizeof(command), false);
+if ( ret )
+return ret;
+
+switch ( its_cmd_get_command(command) )
+{
+case GITS_CMD_SYNC:
+/* We handle ITS commands synchronously, so we ignore SYNC. */
+break;
+default:
+gdprintk(XENLOG_WARNING, "ITS: unhandled ITS command %lu\n",
+ its_cmd_get_command(command));
+break;
+}
+
+its->creadr += ITS_CMD_SIZE;
+if ( its->creadr == ITS_CMD_BUFFER_SIZE(its->cbaser) )
+its->creadr = 0;
+
+if ( ret )
+gdprintk(XENLOG_WARNING,
+ "ITS: ITS command error %d while handling command %lu\n",
+ ret, its_cmd_get_command(command));
+}
+
+return 0;
+}
+
+/*
+ * ITS registers read access *
+ */
+
+static int vgic_v3_its_mmio_read(struct vcpu *v, mmio_info_t *info,
+ register_t *r, void *priv)
+{
+struct virt_its *its = priv;
+uint64_t reg;
+
+switch ( info->gpa & 0x )
+{
+case VREG32(GITS_CTLR):
+if ( info->dabt.size != DABT_WORD ) goto bad_width;
+
+spin_lock(>vcmd_lock);
+spin_lock(>its_lock);
+if ( its->enabled )
+reg = GITS_CTLR_ENABLE;
+else
+reg = 0;
+
+if ( its->cwriter == its->creadr )
+reg |= GITS_CTLR_QUIESCENT;
+spin_unlock(>its_lock);
+spin_unlock(>vcmd_lock);
+
+*r = vgic_reg32_extract(reg, info);
+break;
+case VREG32(GITS_IIDR):
+if ( info->dabt.size != DABT_WORD ) goto bad_width;
+*r = vgic_reg32_extract(GITS_IIDR_VALUE, info);
+break;
+case VREG64(GITS_TYPER):
+if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width;
+
+reg = GITS_TYPER_PHYSICAL;
+reg |= (sizeof(struct vits_itte) - 1) << GITS_TYPER_ITT_SIZE_SHIFT;
+reg |= (its->intid_bits - 1) << GITS_TYPER_IDBITS_SHIFT;
+reg |= (its->devid_bits - 1) << GITS_TYPER_DEVIDS_SHIFT;
+*r = vgic_reg64_extract(reg, info);
+break;
+case VREG64(GITS_CBASER):
+if ( !vgic_reg64_check_access(info->dabt) ) goto bad_width;
+spin_lock(>its_lock);
+*r = vgic_reg64_extract(its->cbaser, info);
+spin_unlock(>its_lock);
+break;
+case VREG64(GITS_CWRITER):
+if ( 

[Xen-devel] [PATCH v5 05/30] ARM: GICv3: allocate LPI pending and property table

2017-04-05 Thread Andre Przywara
The ARM GICv3 provides a new kind of interrupt called LPIs.
The pending bits and the configuration data (priority, enable bits) for
those LPIs are stored in tables in normal memory, which software has to
provide to the hardware.
Allocate the required memory, initialize it and hand it over to each
redistributor. The maximum number of LPIs to be used can be adjusted with
the command line option "max_lpi_bits", which defaults to 20 bits,
covering about one million LPIs.

Signed-off-by: Andre Przywara 
---
 docs/misc/xen-command-line.markdown |   9 ++
 xen/arch/arm/Makefile   |   1 +
 xen/arch/arm/gic-v3-lpi.c   | 221 
 xen/arch/arm/gic-v3.c   |  17 +++
 xen/include/asm-arm/gic_v3_defs.h   |  52 +
 xen/include/asm-arm/gic_v3_its.h|  15 ++-
 xen/include/asm-arm/irq.h   |   8 ++
 7 files changed, 322 insertions(+), 1 deletion(-)
 create mode 100644 xen/arch/arm/gic-v3-lpi.c

diff --git a/docs/misc/xen-command-line.markdown 
b/docs/misc/xen-command-line.markdown
index 9eb85d6..6ef8633 100644
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -1172,6 +1172,15 @@ based interrupts. Any higher IRQs will be available for 
use via PCI MSI.
 ### maxcpus
 > `= `
 
+### max\_lpi\_bits
+> `= `
+
+Specifies the number of ARM GICv3 LPI interrupts to allocate on the host,
+presented as the number of bits needed to encode it. This must be at least
+14 and not exceed 32, and each LPI requires one byte (configuration) and
+one pending bit to be allocated.
+Defaults to 20 bits (to cover at most 1048576 interrupts).
+
 ### mce
 > `= `
 
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 39c0a03..6be85ab 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -19,6 +19,7 @@ obj-y += gic.o
 obj-y += gic-v2.o
 obj-$(CONFIG_HAS_GICV3) += gic-v3.o
 obj-$(CONFIG_HAS_ITS) += gic-v3-its.o
+obj-$(CONFIG_HAS_ITS) += gic-v3-lpi.o
 obj-y += guestcopy.o
 obj-y += hvm.o
 obj-y += io.o
diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
new file mode 100644
index 000..7f99ec6
--- /dev/null
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -0,0 +1,221 @@
+/*
+ * xen/arch/arm/gic-v3-lpi.c
+ *
+ * ARM GICv3 Locality-specific Peripheral Interrupts (LPI) support
+ *
+ * Copyright (C) 2016,2017 - ARM Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see .
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define LPI_PROPTABLE_NEEDS_FLUSHING(1U << 0)
+
+/* Global state */
+static struct {
+/* The global LPI property table, shared by all redistributors. */
+uint8_t *lpi_property;
+/*
+ * Number of physical LPIs the host supports. This is a property of
+ * the GIC hardware. We depart from the habit of naming these things
+ * "physical" in Xen, as the GICv3/4 spec uses the term "physical LPI"
+ * in a different context to differentiate them from "virtual LPIs".
+ */
+unsigned long long int max_host_lpi_ids;
+unsigned int flags;
+} lpi_data;
+
+struct lpi_redist_data {
+void*pending_table;
+};
+
+static DEFINE_PER_CPU(struct lpi_redist_data, lpi_redist);
+
+#define MAX_NR_HOST_LPIS   (lpi_data.max_host_lpi_ids - LPI_OFFSET)
+
+static int gicv3_lpi_allocate_pendtable(uint64_t *reg)
+{
+uint64_t val;
+void *pendtable;
+
+if ( this_cpu(lpi_redist).pending_table )
+return -EBUSY;
+
+val  = GIC_BASER_CACHE_RaWaWb << GICR_PENDBASER_INNER_CACHEABILITY_SHIFT;
+val |= GIC_BASER_CACHE_SameAsInner << 
GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT;
+val |= GIC_BASER_InnerShareable << GICR_PENDBASER_SHAREABILITY_SHIFT;
+
+/*
+ * The pending table holds one bit per LPI and even covers bits for
+ * interrupt IDs below 8192, so we allocate the full range.
+ * The GICv3 imposes a 64KB alignment requirement, also requires
+ * physically contiguous memory.
+ */
+pendtable = _xzalloc(lpi_data.max_host_lpi_ids / 8, SZ_64K);
+if ( !pendtable )
+return -ENOMEM;
+
+/* Make sure the physical address can be encoded in the register. */
+if ( virt_to_maddr(pendtable) & ~GENMASK_ULL(51, 16) )
+{
+xfree(pendtable);
+return -ERANGE;
+}
+clean_and_invalidate_dcache_va_range(pendtable,
+ 

[Xen-devel] [PATCH v5 27/30] ARM: vITS: handle INVALL command

2017-04-05 Thread Andre Przywara
The INVALL command instructs an ITS to invalidate the configuration
data for all LPIs associated with a given redistributor (read: VCPU).
This is nasty to emulate exactly with our architecture, so we just
iterate over all mapped LPIs and filter for those from that particular
VCPU.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c | 62 ++
 1 file changed, 62 insertions(+)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 0d4b20d..9684b3a 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -469,6 +469,65 @@ static int its_handle_inv(struct virt_its *its, uint64_t 
*cmdptr)
 return 0;
 }
 
+/*
+ * INVALL updates the per-LPI configuration status for every LPI mapped to
+ * a particular redistributor.
+ * We iterate over all mapped LPIs in our radix tree and update those.
+ */
+static int its_handle_invall(struct virt_its *its, uint64_t *cmdptr)
+{
+uint32_t collid = its_cmd_get_collection(cmdptr);
+struct vcpu *vcpu;
+struct pending_irq *pirqs[16];
+uint64_t vlpi = 0;  /* 64-bit to catch overflows */
+unsigned int nr_lpis, i;
+int ret = 0;
+
+/*
+ * As this implementation walks over all mapped LPIs, it might take
+ * too long for a real guest, so we might want to revisit this
+ * implementation for DomUs.
+ * However this command is very rare, also we don't expect many
+ * LPIs to be actually mapped, so it's fine for Dom0 to use.
+ */
+ASSERT(is_hardware_domain(its->d));
+
+spin_lock(>its_lock);
+vcpu = get_vcpu_from_collection(its, collid);
+spin_unlock(>its_lock);
+
+read_lock(>d->arch.vgic.pend_lpi_tree_lock);
+
+do
+{
+nr_lpis = radix_tree_gang_lookup(>d->arch.vgic.pend_lpi_tree,
+ (void **)pirqs, vlpi,
+ ARRAY_SIZE(pirqs));
+
+for ( i = 0; i < nr_lpis; i++ )
+{
+/* We only care about LPIs on our VCPU. */
+if ( pirqs[i]->vcpu_id != vcpu->vcpu_id )
+continue;
+
+vlpi = pirqs[i]->irq;
+/* If that fails for a single LPI, carry on to handle the rest. */
+if ( update_lpi_enabled_status(its->d, vcpu, vlpi) )
+ret = -1;
+}
+/*
+ * Loop over the next gang of pending_irqs until we reached the end of
+ * a (fully populated) tree or the lookup function returns less LPIs than
+ * it has been asked for.
+ */
+} while ( (++vlpi < its->d->arch.vgic.nr_lpis) &&
+  (nr_lpis == ARRAY_SIZE(pirqs)) );
+
+read_unlock(>d->arch.vgic.pend_lpi_tree_lock);
+
+return ret;
+}
+
 static int its_handle_mapc(struct virt_its *its, uint64_t *cmdptr)
 {
 uint32_t collid = its_cmd_get_collection(cmdptr);
@@ -711,6 +770,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 case GITS_CMD_INV:
 ret = its_handle_inv(its, command);
 break;
+case GITS_CMD_INVALL:
+ret = its_handle_invall(its, command);
+break;
 case GITS_CMD_MAPC:
 ret = its_handle_mapc(its, command);
 break;
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 20/30] ARM: vITS: handle INT command

2017-04-05 Thread Andre Przywara
The INT command sets a given LPI identified by a DeviceID/EventID pair
as pending and thus triggers it to be injected.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3-its.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 71bc08a..36f942a 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -319,6 +319,33 @@ static int its_handle_clear(struct virt_its *its, uint64_t 
*cmdptr)
 return 0;
 }
 
+static int its_handle_int(struct virt_its *its, uint64_t *cmdptr)
+{
+uint32_t devid = its_cmd_get_deviceid(cmdptr);
+uint32_t eventid = its_cmd_get_id(cmdptr);
+struct pending_irq *p;
+struct vcpu *vcpu;
+uint32_t vlpi;
+
+if ( !read_itte(its, devid, eventid, , ) )
+return -1;
+
+p = its->d->arch.vgic.handler->lpi_to_pending(its->d, vlpi);
+if ( !p )
+return -1;
+
+/*
+ * If the LPI is enabled, inject it.
+ * If not, store the pending state to inject it once it gets enabled later.
+ */
+if ( test_bit(GIC_IRQ_GUEST_ENABLED, >status) )
+vgic_vcpu_inject_irq(vcpu, vlpi);
+else
+set_bit(GIC_IRQ_GUEST_LPI_PENDING, >status);
+
+return 0;
+}
+
 #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
 
 /*
@@ -350,6 +377,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 case GITS_CMD_CLEAR:
 ret = its_handle_clear(its, command);
 break;
+case GITS_CMD_INT:
+ret = its_handle_int(its, command);
+break;
 case GITS_CMD_SYNC:
 /* We handle ITS commands synchronously, so we ignore SYNC. */
 break;
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 30/30] ARM: vGIC: advertise LPI support

2017-04-05 Thread Andre Przywara
To let a guest know about the availability of virtual LPIs, set the
respective bits in the virtual GIC registers and let a guest control
the LPI enable bit.
Only report the LPI capability if the host has initialized at least
one ITS.
This removes a "TBD" comment, as we now populate the processor number
in the GICR_TYPE register.
Advertise 24 bits worth of LPIs to the guest.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3.c | 46 +-
 1 file changed, 41 insertions(+), 5 deletions(-)

diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 3b01247..ba0e79f 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -168,8 +168,12 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
 switch ( gicr_reg )
 {
 case VREG32(GICR_CTLR):
-/* We have not implemented LPI's, read zero */
-goto read_as_zero_32;
+if ( dabt.size != DABT_WORD ) goto bad_width;
+spin_lock(>arch.vgic.lock);
+*r = vgic_reg32_extract(!!(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED),
+info);
+spin_unlock(>arch.vgic.lock);
+return 1;
 
 case VREG32(GICR_IIDR):
 if ( dabt.size != DABT_WORD ) goto bad_width;
@@ -181,16 +185,20 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
 uint64_t typer, aff;
 
 if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
-/* TBD: Update processor id in [23:8] when ITS support is added */
 aff = (MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 3) << 56 |
MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 2) << 48 |
MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 1) << 40 |
MPIDR_AFFINITY_LEVEL(v->arch.vmpidr, 0) << 32);
 typer = aff;
+/* We use the VCPU ID as the redistributor ID in bits[23:8] */
+typer |= (v->vcpu_id & 0x) << 8;
 
 if ( v->arch.vgic.flags & VGIC_V3_RDIST_LAST )
 typer |= GICR_TYPER_LAST;
 
+if ( v->domain->arch.vgic.has_its )
+typer |= GICR_TYPER_PLPIS;
+
 *r = vgic_reg64_extract(typer, info);
 
 return 1;
@@ -411,6 +419,17 @@ static uint64_t sanitize_pendbaser(uint64_t reg)
 return reg;
 }
 
+static void vgic_vcpu_enable_lpis(struct vcpu *v)
+{
+uint64_t reg = v->domain->arch.vgic.rdist_propbase;
+unsigned int nr_lpis = BIT((reg & 0x1f) + 1) - LPI_OFFSET;
+
+if ( !v->domain->arch.vgic.nr_lpis )
+v->domain->arch.vgic.nr_lpis = nr_lpis;
+
+v->arch.vgic.flags |= VGIC_V3_LPIS_ENABLED;
+}
+
 static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info,
   uint32_t gicr_reg,
   register_t r)
@@ -421,8 +440,20 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, 
mmio_info_t *info,
 switch ( gicr_reg )
 {
 case VREG32(GICR_CTLR):
-/* LPI's not implemented */
-goto write_ignore_32;
+if ( dabt.size != DABT_WORD ) goto bad_width;
+if ( !v->domain->arch.vgic.has_its )
+return 1;
+
+spin_lock(>arch.vgic.lock);
+
+/* LPIs can only be enabled once, but never disabled again. */
+if ( (r & GICR_CTLR_ENABLE_LPIS) &&
+ !(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED) )
+vgic_vcpu_enable_lpis(v);
+
+spin_unlock(>arch.vgic.lock);
+
+return 1;
 
 case VREG32(GICR_IIDR):
 /* RO */
@@ -1032,6 +1063,11 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, 
mmio_info_t *info,
 typer = ((ncpus - 1) << GICD_TYPE_CPUS_SHIFT |
  DIV_ROUND_UP(v->domain->arch.vgic.nr_spis, 32));
 
+if ( v->domain->arch.vgic.has_its )
+{
+typer |= GICD_TYPE_LPIS;
+irq_bits = 24;
+}
 typer |= (irq_bits - 1) << GICD_TYPE_ID_BITS_SHIFT;
 
 *r = vgic_reg32_extract(typer, info);
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 02/30] bitops: add BIT_ULL variant

2017-04-05 Thread Andre Przywara
To safely handle 64-bit registers even on 32-bit systems, introduce
a BIT_ULL variant (lifted from Linux).

Signed-off-by: Andre Przywara 
---
 xen/include/asm-arm/bitops.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/xen/include/asm-arm/bitops.h b/xen/include/asm-arm/bitops.h
index bda8898..1cbfb9e 100644
--- a/xen/include/asm-arm/bitops.h
+++ b/xen/include/asm-arm/bitops.h
@@ -24,6 +24,7 @@
 #define BIT(nr) (1UL << (nr))
 #define BIT_MASK(nr)(1UL << ((nr) % BITS_PER_WORD))
 #define BIT_WORD(nr)((nr) / BITS_PER_WORD)
+#define BIT_ULL(nr) (1ULL << (nr))
 #define BITS_PER_BYTE   8
 
 #define ADDR (*(volatile int *) addr)
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 03/30] ARM: GICv3 ITS: parse and store ITS subnodes from hardware DT

2017-04-05 Thread Andre Przywara
Parse the GIC subnodes in the device tree to find every ITS MSI controller
the hardware offers. Store that information in a list to both propagate
all of them later to Dom0, but also to be able to iterate over all ITSes.
This introduces an ITS Kconfig option (as an EXPERT option), use
XEN_CONFIG_EXPERT=y on the make command line to see and use the option.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/Kconfig |  5 +++
 xen/arch/arm/Makefile|  1 +
 xen/arch/arm/gic-v3-its.c| 77 
 xen/arch/arm/gic-v3.c| 10 +++---
 xen/include/asm-arm/gic_v3_its.h | 67 ++
 5 files changed, 156 insertions(+), 4 deletions(-)
 create mode 100644 xen/arch/arm/gic-v3-its.c
 create mode 100644 xen/include/asm-arm/gic_v3_its.h

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 43123e6..d46b98c 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -45,6 +45,11 @@ config ACPI
 config HAS_GICV3
bool
 
+config HAS_ITS
+bool
+prompt "GICv3 ITS MSI controller support" if EXPERT = "y"
+depends on HAS_GICV3
+
 endmenu
 
 menu "ARM errata workaround via the alternative framework"
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 0ce94a8..39c0a03 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -18,6 +18,7 @@ obj-$(EARLY_PRINTK) += early_printk.o
 obj-y += gic.o
 obj-y += gic-v2.o
 obj-$(CONFIG_HAS_GICV3) += gic-v3.o
+obj-$(CONFIG_HAS_ITS) += gic-v3-its.o
 obj-y += guestcopy.o
 obj-y += hvm.o
 obj-y += io.o
diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
new file mode 100644
index 000..6b02349
--- /dev/null
+++ b/xen/arch/arm/gic-v3-its.c
@@ -0,0 +1,77 @@
+/*
+ * xen/arch/arm/gic-v3-its.c
+ *
+ * ARM GICv3 Interrupt Translation Service (ITS) support
+ *
+ * Copyright (C) 2016,2017 - ARM Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; If not, see .
+ */
+
+#include 
+#include 
+#include 
+
+/*
+ * No lock here, as this list gets only populated upon boot while scanning
+ * firmware tables for all host ITSes, and only gets iterated afterwards.
+ */
+LIST_HEAD(host_its_list);
+
+bool gicv3_its_host_has_its(void)
+{
+return !list_empty(_its_list);
+}
+
+/* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */
+void gicv3_its_dt_init(const struct dt_device_node *node)
+{
+const struct dt_device_node *its = NULL;
+struct host_its *its_data;
+
+/*
+ * Check for ITS MSI subnodes. If any, add the ITS register
+ * frames to the ITS list.
+ */
+dt_for_each_child_node(node, its)
+{
+uint64_t addr, size;
+
+if ( !dt_device_is_compatible(its, "arm,gic-v3-its") )
+continue;
+
+if ( dt_device_get_address(its, 0, , ) )
+panic("GICv3: Cannot find a valid ITS frame address");
+
+its_data = xzalloc(struct host_its);
+if ( !its_data )
+panic("GICv3: Cannot allocate memory for ITS frame");
+
+its_data->addr = addr;
+its_data->size = size;
+its_data->dt_node = its;
+
+printk("GICv3: Found ITS @0x%lx\n", addr);
+
+list_add_tail(_data->entry, _its_list);
+}
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 695f01f..b626298 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -42,6 +42,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -1227,11 +1228,12 @@ static void __init gicv3_dt_init(void)
  */
 res = dt_device_get_address(node, 1 + gicv3.rdist_count,
 , );
-if ( res )
-return;
+if ( !res )
+dt_device_get_address(node, 1 + gicv3.rdist_count + 2,
+  , );
 
-dt_device_get_address(node, 1 + gicv3.rdist_count + 2,
-  , );
+/* Check for ITS child nodes and build the host ITS list accordingly. */
+gicv3_its_dt_init(node);
 }
 
 static int gicv3_iomem_deny_access(const struct domain *d)
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
new file mode 100644
index 000..765a655
--- /dev/null
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -0,0 +1,67 @@
+/*
+ * ARM GICv3 

[Xen-devel] [PATCH v5 24/30] ARM: vITS: handle MOVI command

2017-04-05 Thread Andre Przywara
The MOVI command moves the interrupt affinity from one redistributor
(read: VCPU) to another.
For now migration of "live" LPIs is not yet implemented, but we store
the changed affinity in the host LPI structure and in our virtual ITTE.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/gic-v3-its.c| 24 
 xen/arch/arm/gic-v3-lpi.c| 15 +
 xen/arch/arm/vgic-v3-its.c   | 47 
 xen/include/asm-arm/gic_v3_its.h |  4 
 4 files changed, 90 insertions(+)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index d970119..a57e63a 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -851,6 +851,30 @@ struct pending_irq *gicv3_assign_guest_event(struct domain 
*d,
 return pirq;
 }
 
+/* Changes the target VCPU for a given host LPI assigned to a domain. */
+int gicv3_lpi_change_vcpu(struct domain *d, paddr_t vdoorbell,
+  uint32_t vdevid, uint32_t veventid,
+  unsigned int vcpu_id)
+{
+uint32_t host_lpi;
+struct its_devices *dev;
+
+spin_lock(>arch.vgic.its_devices_lock);
+dev = get_its_device(d, vdoorbell, vdevid);
+if ( dev )
+host_lpi = get_host_lpi(dev, veventid);
+else
+host_lpi = 0;
+spin_unlock(>arch.vgic.its_devices_lock);
+
+if ( !host_lpi )
+return -ENOENT;
+
+gicv3_lpi_update_host_vcpuid(host_lpi, vcpu_id);
+
+return 0;
+}
+
 /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */
 void gicv3_its_dt_init(const struct dt_device_node *node)
 {
diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
index c997ed5..b9960aa 100644
--- a/xen/arch/arm/gic-v3-lpi.c
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -234,6 +234,21 @@ void gicv3_lpi_update_host_entry(uint32_t host_lpi, int 
domain_id,
 write_u64_atomic(>data, hlpi.data);
 }
 
+int gicv3_lpi_update_host_vcpuid(uint32_t host_lpi, unsigned int vcpu_id)
+{
+union host_lpi *hlpip;
+
+ASSERT(host_lpi >= LPI_OFFSET);
+
+host_lpi -= LPI_OFFSET;
+
+hlpip = _data.host_lpis[host_lpi / HOST_LPIS_PER_PAGE][host_lpi % 
HOST_LPIS_PER_PAGE];
+
+write_u16_atomic(>vcpu_id, vcpu_id);
+
+return 0;
+}
+
 static int gicv3_lpi_allocate_pendtable(uint64_t *reg)
 {
 uint64_t val;
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 079dd44..6afb915 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -508,6 +508,47 @@ static int its_handle_mapti(struct virt_its *its, uint64_t 
*cmdptr)
 return 0;
 }
 
+static int its_handle_movi(struct virt_its *its, uint64_t *cmdptr)
+{
+uint32_t devid = its_cmd_get_deviceid(cmdptr);
+uint32_t eventid = its_cmd_get_id(cmdptr);
+int collid = its_cmd_get_collection(cmdptr);
+struct pending_irq *p;
+struct vcpu *vcpu;
+uint32_t vlpi;
+int ret = -1;
+
+spin_lock(>its_lock);
+/* Check for a mapped LPI and get the LPI number. */
+if ( !read_itte_locked(its, devid, eventid, , ) )
+goto out_unlock;
+
+/* Check the new collection ID and get the new VCPU pointer */
+vcpu = get_vcpu_from_collection(its, collid);
+if ( !vcpu )
+goto out_unlock;
+
+/* Update our cached vcpu_id in the pending_irq. */
+p = its->d->arch.vgic.handler->lpi_to_pending(its->d, vlpi);
+p->vcpu_id = vcpu->vcpu_id;
+
+/* Now store the new collection in the translation table. */
+if ( !write_itte_locked(its, devid, eventid, collid, vlpi, ) )
+goto out_unlock;
+
+spin_unlock(>its_lock);
+
+/* TODO: lookup currently-in-guest virtual IRQs and migrate them? */
+
+return gicv3_lpi_change_vcpu(its->d, its->doorbell_address,
+ devid, eventid, vcpu->vcpu_id);
+
+out_unlock:
+spin_unlock(>its_lock);
+
+return ret;
+}
+
 #define ITS_CMD_BUFFER_SIZE(baser)  baser) & 0xff) + 1) << 12)
 
 /*
@@ -552,6 +593,12 @@ static int vgic_its_handle_cmds(struct domain *d, struct 
virt_its *its)
 case GITS_CMD_MAPTI:
 ret = its_handle_mapti(its, command);
 break;
+case GITS_CMD_MOVALL:
+gdprintk(XENLOG_G_INFO, "ITS: ignoring MOVALL command\n");
+break;
+case GITS_CMD_MOVI:
+ret = its_handle_movi(its, command);
+break;
 case GITS_CMD_SYNC:
 /* We handle ITS commands synchronously, so we ignore SYNC. */
 break;
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index 30aa1ef..daae143 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -177,8 +177,12 @@ void gicv3_free_host_lpi_block(uint32_t first_lpi);
 struct pending_irq *gicv3_assign_guest_event(struct domain *d, paddr_t 
doorbell,
  uint32_t devid, uint32_t eventid,

[Xen-devel] [PATCH v5 07/30] ARM: GICv3 ITS: map ITS command buffer

2017-04-05 Thread Andre Przywara
Instead of directly manipulating the tables in memory, an ITS driver
sends commands via a ring buffer in normal system memory to the ITS h/w
to create or alter the LPI mappings.
Allocate memory for that buffer and tell the ITS about it to be able
to send ITS commands.

Signed-off-by: Andre Przywara 
Reviewed-by: Stefano Stabellini 
---
 xen/arch/arm/gic-v3-its.c| 53 
 xen/include/asm-arm/gic_v3_its.h |  6 +
 2 files changed, 59 insertions(+)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index eef2933..d8e978a 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -20,10 +20,13 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 
+#define ITS_CMD_QUEUE_SZSZ_1M
+
 /*
  * No lock here, as this list gets only populated upon boot while scanning
  * firmware tables for all host ITSes, and only gets iterated afterwards.
@@ -60,6 +63,51 @@ static uint64_t encode_baser_phys_addr(paddr_t addr, 
unsigned int page_bits)
 return ret | ((addr & GENMASK_ULL(51, 48)) >> (48 - 12));
 }
 
+static void *its_map_cbaser(struct host_its *its)
+{
+void __iomem *cbasereg = its->its_base + GITS_CBASER;
+uint64_t reg;
+void *buffer;
+
+reg  = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT;
+reg |= GIC_BASER_CACHE_SameAsInner << GITS_BASER_OUTER_CACHEABILITY_SHIFT;
+reg |= GIC_BASER_CACHE_RaWaWb << GITS_BASER_INNER_CACHEABILITY_SHIFT;
+
+buffer = _xzalloc(ITS_CMD_QUEUE_SZ, SZ_64K);
+if ( !buffer )
+return NULL;
+
+if ( virt_to_maddr(buffer) & ~GENMASK_ULL(51, 12) )
+{
+xfree(buffer);
+return NULL;
+}
+
+reg |= GITS_VALID_BIT | virt_to_maddr(buffer);
+reg |= ((ITS_CMD_QUEUE_SZ / SZ_4K) - 1) & GITS_CBASER_SIZE_MASK;
+writeq_relaxed(reg, cbasereg);
+reg = readq_relaxed(cbasereg);
+
+/* If the ITS dropped shareability, drop cacheability as well. */
+if ( (reg & GITS_BASER_SHAREABILITY_MASK) == 0 )
+{
+reg &= ~GITS_BASER_INNER_CACHEABILITY_MASK;
+writeq_relaxed(reg, cbasereg);
+}
+
+/*
+ * If the command queue memory is mapped as uncached, we need to flush
+ * it on every access.
+ */
+if ( !(reg & GITS_BASER_INNER_CACHEABILITY_MASK) )
+{
+its->flags |= HOST_ITS_FLUSH_CMD_QUEUE;
+printk(XENLOG_WARNING "using non-cacheable ITS command queue\n");
+}
+
+return buffer;
+}
+
 /* The ITS BASE registers work with page sizes of 4K, 16K or 64K. */
 #define BASER_PAGE_BITS(sz) ((sz) * 2 + 12)
 
@@ -180,6 +228,11 @@ static int gicv3_its_init_single_its(struct host_its 
*hw_its)
 }
 }
 
+hw_its->cmd_buf = its_map_cbaser(hw_its);
+if ( !hw_its->cmd_buf )
+return -ENOMEM;
+writeq_relaxed(0, hw_its->its_base + GITS_CWRITER);
+
 return 0;
 }
 
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index 6e51b98..a68ccf3 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -84,8 +84,12 @@
 #define GITS_BASER_OUTER_CACHEABILITY_MASK   (0x7ULL << 
GITS_BASER_OUTER_CACHEABILITY_SHIFT)
 #define GITS_BASER_INNER_CACHEABILITY_MASK   (0x7ULL << 
GITS_BASER_INNER_CACHEABILITY_SHIFT)
 
+#define GITS_CBASER_SIZE_MASK   0xff
+
 #include 
 
+#define HOST_ITS_FLUSH_CMD_QUEUE(1U << 0)
+
 /* data structure for each hardware ITS */
 struct host_its {
 struct list_head entry;
@@ -96,6 +100,8 @@ struct host_its {
 unsigned int devid_bits;
 unsigned int evid_bits;
 unsigned int itte_size;
+void *cmd_buf;
+unsigned int flags;
 };
 
 
-- 
2.8.2


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v5 15/30] ARM: vGICv3: handle virtual LPI pending and property tables

2017-04-05 Thread Andre Przywara
Allow a guest to provide the address and size for the memory regions
it has reserved for the GICv3 pending and property tables.
We sanitise the various fields of the respective redistributor
registers and map those pages into Xen's address space to have easy
access.
This introduces a function to read and write from and to guest memory,
to be later able to access the tables located there.
This vgic_access_guest_memory() function has been written by Vijaya Kumar
as part of an earlier series.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3.c   | 152 ++-
 xen/arch/arm/vgic.c  |  39 +++
 xen/include/asm-arm/domain.h |   6 +-
 xen/include/asm-arm/vgic.h   |   3 +
 4 files changed, 182 insertions(+), 18 deletions(-)

diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 2a14305..0623803 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -19,12 +19,14 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -228,12 +230,21 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
 goto read_reserved;
 
 case VREG64(GICR_PROPBASER):
-/* LPI's not implemented */
-goto read_as_zero_64;
+if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
+
+spin_lock(>arch.vgic.lock);
+*r = vgic_reg64_extract(v->domain->arch.vgic.rdist_propbase, info);
+spin_unlock(>arch.vgic.lock);
+return 1;
 
 case VREG64(GICR_PENDBASER):
-/* LPI's not implemented */
-goto read_as_zero_64;
+if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
+
+spin_lock(>arch.vgic.lock);
+*r = vgic_reg64_extract(v->arch.vgic.rdist_pendbase, info);
+*r &= ~GICR_PENDBASER_PTZ;   /* WO, reads as 0 */
+spin_unlock(>arch.vgic.lock);
+return 1;
 
 case 0x0080:
 goto read_reserved;
@@ -301,11 +312,6 @@ bad_width:
 domain_crash_synchronous();
 return 0;
 
-read_as_zero_64:
-if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
-*r = 0;
-return 1;
-
 read_as_zero_32:
 if ( dabt.size != DABT_WORD ) goto bad_width;
 *r = 0;
@@ -330,11 +336,95 @@ read_unknown:
 return 1;
 }
 
+static uint64_t vgic_sanitise_field(uint64_t reg, uint64_t field_mask,
+int field_shift,
+uint64_t (*sanitise_fn)(uint64_t))
+{
+uint64_t field = (reg & field_mask) >> field_shift;
+
+field = sanitise_fn(field) << field_shift;
+
+return (reg & ~field_mask) | field;
+}
+
+/* We want to avoid outer shareable. */
+static uint64_t vgic_sanitise_shareability(uint64_t field)
+{
+switch ( field )
+{
+case GIC_BASER_OuterShareable:
+return GIC_BASER_InnerShareable;
+default:
+return field;
+}
+}
+
+/* Avoid any inner non-cacheable mapping. */
+static uint64_t vgic_sanitise_inner_cacheability(uint64_t field)
+{
+switch ( field )
+{
+case GIC_BASER_CACHE_nCnB:
+case GIC_BASER_CACHE_nC:
+return GIC_BASER_CACHE_RaWb;
+default:
+return field;
+}
+}
+
+/* Non-cacheable or same-as-inner are OK. */
+static uint64_t vgic_sanitise_outer_cacheability(uint64_t field)
+{
+switch ( field )
+{
+case GIC_BASER_CACHE_SameAsInner:
+case GIC_BASER_CACHE_nC:
+return field;
+default:
+return GIC_BASER_CACHE_nC;
+}
+}
+
+static uint64_t sanitize_propbaser(uint64_t reg)
+{
+reg = vgic_sanitise_field(reg, GICR_PROPBASER_SHAREABILITY_MASK,
+  GICR_PROPBASER_SHAREABILITY_SHIFT,
+  vgic_sanitise_shareability);
+reg = vgic_sanitise_field(reg, GICR_PROPBASER_INNER_CACHEABILITY_MASK,
+  GICR_PROPBASER_INNER_CACHEABILITY_SHIFT,
+  vgic_sanitise_inner_cacheability);
+reg = vgic_sanitise_field(reg, GICR_PROPBASER_OUTER_CACHEABILITY_MASK,
+  GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT,
+  vgic_sanitise_outer_cacheability);
+
+reg &= ~GICR_PROPBASER_RES0_MASK;
+
+return reg;
+}
+
+static uint64_t sanitize_pendbaser(uint64_t reg)
+{
+reg = vgic_sanitise_field(reg, GICR_PENDBASER_SHAREABILITY_MASK,
+  GICR_PENDBASER_SHAREABILITY_SHIFT,
+  vgic_sanitise_shareability);
+reg = vgic_sanitise_field(reg, GICR_PENDBASER_INNER_CACHEABILITY_MASK,
+  GICR_PENDBASER_INNER_CACHEABILITY_SHIFT,
+  vgic_sanitise_inner_cacheability);
+reg = vgic_sanitise_field(reg, GICR_PENDBASER_OUTER_CACHEABILITY_MASK,
+  GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT,
+  vgic_sanitise_outer_cacheability);
+
+

[Xen-devel] [qemu-mainline baseline-only test] 71151: regressions - trouble: blocked/broken/fail/pass

2017-04-05 Thread Platform Team regression test user
This run is configured for baseline tests only.

flight 71151 qemu-mainline real [real]
http://osstest.xs.citrite.net/~osstest/testlogs/logs/71151/

Regressions :-(

Tests which did not succeed and are blocking,
including tests which could not be run:
 test-amd64-i386-xl-qemuu-winxpsp3-vcpus1 9 windows-install fail REGR. vs. 71147

Regressions which are regarded as allowable (not blocking):
 test-armhf-armhf-libvirt-xsm 13 saverestore-support-checkfail   like 71147
 test-armhf-armhf-libvirt 13 saverestore-support-checkfail   like 71147
 test-armhf-armhf-libvirt-raw 12 saverestore-support-checkfail   like 71147
 test-amd64-amd64-qemuu-nested-intel 16 debian-hvm-install/l1/l2 fail like 71147

Tests which did not succeed, but are not blocking:
 test-arm64-arm64-libvirt-xsm  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl   1 build-check(1)   blocked  n/a
 build-arm64-libvirt   1 build-check(1)   blocked  n/a
 test-arm64-arm64-libvirt-qcow2  1 build-check(1)   blocked  n/a
 test-arm64-arm64-libvirt  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-credit2   1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-rtds  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-multivcpu  1 build-check(1)   blocked  n/a
 test-arm64-arm64-xl-xsm   1 build-check(1)   blocked  n/a
 build-arm64   2 hosts-allocate   broken never pass
 build-arm64-pvops 2 hosts-allocate   broken never pass
 build-arm64   3 capture-logs broken never pass
 build-arm64-pvops 3 capture-logs broken never pass
 build-arm64-xsm   2 hosts-allocate   broken never pass
 build-arm64-xsm   3 capture-logs broken never pass
 test-armhf-armhf-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-xsm  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-xsm  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-midway   12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-midway   13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-credit2  12 migrate-support-checkfail   never pass
 test-armhf-armhf-libvirt 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-credit2  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl  13 saverestore-support-checkfail   never pass
 test-armhf-armhf-xl-multivcpu 12 migrate-support-checkfail  never pass
 test-armhf-armhf-xl-multivcpu 13 saverestore-support-checkfail  never pass
 test-amd64-amd64-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-rtds 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-rtds 13 saverestore-support-checkfail   never pass
 test-amd64-amd64-libvirt 12 migrate-support-checkfail   never pass
 test-amd64-i386-libvirt-xsm  12 migrate-support-checkfail   never pass
 test-amd64-i386-libvirt  12 migrate-support-checkfail   never pass
 test-armhf-armhf-libvirt-raw 11 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-armhf-armhf-xl-vhd  11 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-vhd  12 saverestore-support-checkfail   never pass
 test-amd64-amd64-qemuu-nested-amd 16 debian-hvm-install/l1/l2  fail never pass
 test-amd64-amd64-libvirt-vhd 11 migrate-support-checkfail   never pass
 test-amd64-amd64-xl-qemuu-win7-amd64 16 guest-stop fail never pass
 test-amd64-i386-xl-qemuu-win7-amd64 16 guest-stop  fail never pass

version targeted for testing:
 qemuufa902c8ca0f3b83e0e3dda1e9e00f0b1d28e718a
baseline version:
 qemuub1a419ec79c2451fd7b6acfb415a02881ad77844

Last test of basis71147  2017-04-04 07:50:06 Z1 days
Testing same since71151  2017-04-05 15:44:42 Z0 days1 attempts


People who touched revisions under test:
  Corey Minyard 
  Daniel P. Berrange 
  Paolo Bonzini 
  Peter Maydell 
  Richard W.M. Jones 
  Stefan Hajnoczi 
  Tejaswini Poluri 
  Wang guang 
  Wang Guang
  yaolujing 
  zhanghailiang 

jobs:
 

Re: [Xen-devel] [PATCH] arm64: xen: Implement EFI reset_system callback

2017-04-05 Thread Stefano Stabellini
On Wed, 5 Apr 2017, Julien Grall wrote:
> When rebooting DOM0 with ACPI, the kernel is crashing with the stack trace 
> [1].
> 
> This is happening because when EFI runtimes are enabled, the reset code
> (see machin_restart) will first try to use EFI restart method.
> 
> However, the EFI restart code is expecting the reset_system callback to
> be always set. This is not the case for Xen and will lead to crash.
> 
> Looking at the reboot path, it is expected to fallback on an alternative
> reboot method if one does not work. So implement reset_system callback
> as a NOP for Xen.
> 
> [   36.999270] reboot: Restarting system
> [   37.002921] Internal error: Attempting to execute userspace memory: 
> 8604 [#1] PREEMPT SMP
> [   37.011460] Modules linked in:
> [   37.014598] CPU: 0 PID: 1 Comm: systemd-shutdow Not tainted 
> 4.11.0-rc1-3-g1e248b60a39b-dirty #506
> [   37.023903] Hardware name: (null) (DT)
> [   37.027734] task: 800902068000 task.stack: 800902064000
> [   37.033739] PC is at 0x0
> [   37.036359] LR is at efi_reboot+0x94/0xd0
> [   37.040438] pc : [<>] lr : [] pstate: 
> 404001c5
> [   37.047920] sp : 800902067cf0
> [   37.051314] x29: 800902067cf0 x28: 800902068000
> [   37.056709] x27: 08992000 x26: 008e
> [   37.062104] x25: 0123 x24: 0015
> [   37.067499] x23:  x22: 08e6e250
> [   37.072894] x21: 08e6e000 x20: 
> [   37.078289] x19: 08e5d4c8 x18: 0010
> [   37.083684] x17: a7c27470 x16: deadbeef
> [   37.089079] x15: 0006 x14: 88f42bef
> [   37.094474] x13: 08f42bfd x12: 08e706c0
> [   37.099870] x11: 08e7 x10: 05f5e0ff
> [   37.105265] x9 : 800902067a50 x8 : 6974726174736552
> [   37.110660] x7 : 08cc6fb8 x6 : 08cc6fb0
> [   37.116055] x5 : 08c97dd8 x4 : 
> [   37.121453] x3 :  x2 : 
> [   37.126845] x1 :  x0 : 
> [   37.132239]
> [   37.133808] Process systemd-shutdow (pid: 1, stack limit = 
> 0x800902064000)
> [   37.141118] Stack: (0x800902067cf0 to 0x800902068000)
> [   37.146949] 7ce0:   800902067d40 
> 08085334
> [   37.154869] 7d00:  08f3b000 800902067d40 
> 080852e0
> [   37.162787] 7d20: 08cc6fb0 08cc6fb8 08c7f580 
> 08c97dd8
> [   37.170706] 7d40: 800902067d60 080e2c2c  
> 01234567
> [   37.178624] 7d60: 800902067d80 080e2ee8  
> 080e2df4
> [   37.186544] 7d80:  080830f0  
> 8008ff1c1000
> [   37.194462] 7da0:  a7c4b1cc  
> 0024
> [   37.202380] 7dc0: 800902067dd0 0005 f24743c8 
> 0004
> [   37.210299] 7de0: f2475f03 0010 f2474418 
> 0005
> [   37.218218] 7e00: f2474578 000a d6b722c0 
> 0001
> [   37.226136] 7e20: 0123 0038 800902067e50 
> 081e7294
> [   37.234055] 7e40: 800902067e60 081e935c 800902067e60 
> 081e9388
> [   37.241973] 7e60: 800902067eb0 081ea388  
> 8008ff1c1000
> [   37.249892] 7e80:  a7c4a79c  
> 0002
> [   37.257810] 7ea0: 0104   
> 080830f0
> [   37.265729] 7ec0: fee1dead 28121969 01234567 
> 
> [   37.273651] 7ee0:  80800080 80008080 
> feffa9a9d4ff2d66
> [   37.281567] 7f00: 008e feffa9a9d5b60e0f 7f7f7f7f 
> 0101010101010101
> [   37.289485] 7f20: 0010 0008 003a 
> a7ccf588
> [   37.297404] 7f40: d6b87d00 a7c4b1b0 f2474be0 
> d6b88000
> [   37.305326] 7f60: f2474fb0 01234567  
> 
> [   37.313240] 7f80:  0001 d6b70d4d 
> 
> [   37.321159] 7fa0: 0001 f2474ea0 d6b5e2e0 
> f2474e80
> [   37.329078] 7fc0: a7c4b1cc  fee1dead 
> 008e
> [   37.336997] 7fe0:   9ce839cffee77eab 
> fafdbf9f7ed57f2f
> [   37.344911] Call trace:
> [   37.347437] Exception stack(0x800902067b20 to 0x800902067c50)
> [   37.353970] 7b20: 08e5d4c8 0001 80f82000 
> 
> [   37.361883] 7b40: 800902067b60 08e17000 08f44c68 
> 0001081081b4
> [   37.369802] 7b60: 800902067bf0 08108478  
> 

[Xen-devel] [PATCH v7 1/2] arm: remove irq from inflight, then change physical affinity

2017-04-05 Thread Stefano Stabellini
This patch fixes a potential race that could happen when
gic_update_one_lr and vgic_vcpu_inject_irq run simultaneously.

When GIC_IRQ_GUEST_MIGRATING is set, we must make sure that the irq has
been removed from inflight before changing physical affinity, to avoid
concurrent accesses to p->inflight, as vgic_vcpu_inject_irq will take a
different vcpu lock.

Signed-off-by: Stefano Stabellini 
Reviewed-by: Julien Grall 
---
 xen/arch/arm/gic.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 9522c6c..2455d8f 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -503,6 +503,13 @@ static void gic_update_one_lr(struct vcpu *v, int i)
 gic_raise_guest_irq(v, irq, p->priority);
 else {
 list_del_init(>inflight);
+/* 
+ * Remove from inflight, then change physical affinity. It
+ * makes sure that when a new interrupt is received on the
+ * next pcpu, inflight is already cleared. No concurrent
+ * accesses to inflight.
+ */
+smp_wmb();
 if ( test_and_clear_bit(GIC_IRQ_GUEST_MIGRATING, >status) )
 {
 struct vcpu *v_target = vgic_get_target_vcpu(v, irq);
-- 
1.9.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v7 0/2] xen/arm: remove race conditions in irq migration

2017-04-05 Thread Stefano Stabellini
Hi all,

this patch series removes three race conditions affecting the current
code base.

The first race condition is between gic_update_one_lr and
vgic_vcpu_inject_irq: as soon as gic_update_one_lr calls
irq_set_affinity a new interrupt could be injected in the new pcpu,
eventually vgic_vcpu_inject_irq is called which manipulates the inflight
list. The first patch solves this race by adding a barrier in
gic_update_one_lr. This patch was suggested by Julien.

The second race condition happens when gic_update_one_lr runs
simultaneously with vgic_store_itargetsr and vgic_migrate_irq. Setting
the new target is done after calling vgic_migrate_irq, which means that
gic_update_one_lr could end up setting the physical affinity to the one
of the old pcpu.

The third race condition happens again between gic_update_one_lr and
vgic_migrate_irq: when GIC_IRQ_GUEST_MIGRATING is already set and
vgic_migrate_irq is called again, it will take a different vgic lock
from the one that gic_update_one_lr is taking.

The second patch addressed the last two issues by refusing any irq
migration requests while one request is already in-progress and not yet
completed.


For your reference, it is not possible to take the p->desc lock from
gic_update_one_lr, because the correct lock ordering is p->desc lock,
then vgic lock.


Changes in v7:
- add reviewed-by
- code style fix
- s/%d/%u
- gdprintk/gprintk

Changes in v6:
- smp_mb/smb_wmb
- refuse nested irq migration requests instead of trying to handle them


Stefano Stabellini (2):
  arm: remove irq from inflight, then change physical affinity
  vgic: refuse irq migration when one is already in progress

 xen/arch/arm/gic.c | 10 +-
 xen/arch/arm/vgic-v2.c |  7 +++
 xen/arch/arm/vgic-v3.c |  7 ---
 xen/arch/arm/vgic.c| 14 +-
 xen/include/asm-arm/vgic.h |  2 +-
 5 files changed, 26 insertions(+), 14 deletions(-)

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v7 2/2] vgic: refuse irq migration when one is already in progress

2017-04-05 Thread Stefano Stabellini
When an irq migration is already in progress, but not yet completed
(GIC_IRQ_GUEST_MIGRATING is set), refuse any other irq migration
requests for the same irq.

This patch implements this approach by returning success or failure from
vgic_migrate_irq, and avoiding irq target changes on failure. It prints
a warning in case the irq migration fails.

It also moves the clear_bit of GIC_IRQ_GUEST_MIGRATING to after the
physical irq affinity has been changed so that all operations regarding
irq migration are completed.

Signed-off-by: Stefano Stabellini 
---
 xen/arch/arm/gic.c |  3 ++-
 xen/arch/arm/vgic-v2.c |  7 +++
 xen/arch/arm/vgic-v3.c |  7 ---
 xen/arch/arm/vgic.c| 14 +-
 xen/include/asm-arm/vgic.h |  2 +-
 5 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 2455d8f..f943931 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -510,10 +510,11 @@ static void gic_update_one_lr(struct vcpu *v, int i)
  * accesses to inflight.
  */
 smp_wmb();
-if ( test_and_clear_bit(GIC_IRQ_GUEST_MIGRATING, >status) )
+if ( test_bit(GIC_IRQ_GUEST_MIGRATING, >status) )
 {
 struct vcpu *v_target = vgic_get_target_vcpu(v, irq);
 irq_set_affinity(p->desc, cpumask_of(v_target->processor));
+clear_bit(GIC_IRQ_GUEST_MIGRATING, >status);
 }
 }
 }
diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
index 0674f7b..dc9f95b 100644
--- a/xen/arch/arm/vgic-v2.c
+++ b/xen/arch/arm/vgic-v2.c
@@ -156,12 +156,11 @@ static void vgic_store_itargetsr(struct domain *d, struct 
vgic_irq_rank *rank,
 /* Only migrate the vIRQ if the target vCPU has changed */
 if ( new_target != old_target )
 {
-vgic_migrate_irq(d->vcpu[old_target],
+if ( vgic_migrate_irq(d->vcpu[old_target],
  d->vcpu[new_target],
- virq);
+ virq) )
+write_atomic(>vcpu[offset], new_target);
 }
-
-write_atomic(>vcpu[offset], new_target);
 }
 }
 
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 0679e76..1e9890b 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -151,9 +151,10 @@ static void vgic_store_irouter(struct domain *d, struct 
vgic_irq_rank *rank,
 
 /* Only migrate the IRQ if the target vCPU has changed */
 if ( new_vcpu != old_vcpu )
-vgic_migrate_irq(old_vcpu, new_vcpu, virq);
-
-write_atomic(>vcpu[offset], new_vcpu->vcpu_id);
+{
+if ( vgic_migrate_irq(old_vcpu, new_vcpu, virq) )
+write_atomic(>vcpu[offset], new_vcpu->vcpu_id);
+}
 }
 
 static inline bool vgic_reg64_check_access(struct hsr_dabt dabt)
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 67d75a6..83569b0 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -237,18 +237,21 @@ static int vgic_get_virq_priority(struct vcpu *v, 
unsigned int virq)
 return priority;
 }
 
-void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq)
+bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq)
 {
 unsigned long flags;
 struct pending_irq *p = irq_to_pending(old, irq);
 
 /* nothing to do for virtual interrupts */
 if ( p->desc == NULL )
-return;
+return true;
 
 /* migration already in progress, no need to do anything */
 if ( test_bit(GIC_IRQ_GUEST_MIGRATING, >status) )
-return;
+{
+gprintk(XENLOG_WARNING, "irq %u migration failed: requested while in 
progress\n", irq);
+return false;
+}
 
 perfc_incr(vgic_irq_migrates);
 
@@ -258,7 +261,7 @@ void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
 {
 irq_set_affinity(p->desc, cpumask_of(new->processor));
 spin_unlock_irqrestore(>arch.vgic.lock, flags);
-return;
+return true;
 }
 /* If the IRQ is still lr_pending, re-inject it to the new vcpu */
 if ( !list_empty(>lr_queue) )
@@ -269,7 +272,7 @@ void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
 irq_set_affinity(p->desc, cpumask_of(new->processor));
 spin_unlock_irqrestore(>arch.vgic.lock, flags);
 vgic_vcpu_inject_irq(new, irq);
-return;
+return true;
 }
 /* if the IRQ is in a GICH_LR register, set GIC_IRQ_GUEST_MIGRATING
  * and wait for the EOI */
@@ -277,6 +280,7 @@ void vgic_migrate_irq(struct vcpu *old, struct vcpu *new, 
unsigned int irq)
 set_bit(GIC_IRQ_GUEST_MIGRATING, >status);
 
 spin_unlock_irqrestore(>arch.vgic.lock, flags);
+return true;
 }
 
 void arch_move_irqs(struct vcpu *v)
diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h
index 894c3f1..544867a 100644
--- 

[Xen-devel] [PATCH v2] x86/vpmu_intel: Handle SMT consistently for programmable and fixed counters

2017-04-05 Thread Mohit Gambhir
The patch introduces a macro FIXED_CTR_CTRL_ANYTHREAD_MASK and uses it
to mask .Anythread bit for all counter in IA32_FIXED_CTR_CTRL MSR in all
versions of Intel Arhcitectural Performance Monitoring.  Masking .AnyThread bit
 is necesssry for two reasons:

1. We need to be consistent in the implementation. We disable .Anythread bit in
programmable counters (regardless of the version) by masking bit 21 in
IA32_PERFEVTSELx.  (See code snippet below from vpmu_intel.c)

 /* Masks used for testing whether and MSR is valid */
 #define ARCH_CTRL_MASK  (~((1ull << 32) - 1) | (1ull << 21))

But we leave it enabled in fixed function counters for version 3. Removing the
condition disables the bit in fixed function counters regardless of the version,
which is consistent with what is done for programmable counters.

2. We don't want to expose event counts from another guest (or hypervisor)
which can happen if .AnyThread bit is not masked and a VCPU is only scheduled
to run on one of the hardware threads in a hyper-threaded CPU.

Also, note that Intel SDM discourages the  use of .AnyThread bit in virtualized
 environments (per section 18.2.3.1 AnyThread Counting and Software Evolution).

Signed-off-by: Mohit Gambhir 
---
 xen/arch/x86/cpu/vpmu_intel.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/cpu/vpmu_intel.c b/xen/arch/x86/cpu/vpmu_intel.c
index 0d66ecb..3f0322c 100644
--- a/xen/arch/x86/cpu/vpmu_intel.c
+++ b/xen/arch/x86/cpu/vpmu_intel.c
@@ -73,6 +73,7 @@ static bool_t __read_mostly full_width_write;
  */
 #define FIXED_CTR_CTRL_BITS 4
 #define FIXED_CTR_CTRL_MASK ((1 << FIXED_CTR_CTRL_BITS) - 1)
+#define FIXED_CTR_CTRL_ANYTHREAD_MASK 0x4
 
 #define ARCH_CNTR_ENABLED   (1ULL << 22)
 
@@ -946,6 +947,7 @@ int __init core2_vpmu_init(void)
 {
 u64 caps;
 unsigned int version = 0;
+unsigned int i;
 
 if ( current_cpu_data.cpuid_level >= 0xa )
 version = MASK_EXTR(cpuid_eax(0xa), PMU_VERSION_MASK);
@@ -979,8 +981,11 @@ int __init core2_vpmu_init(void)
 full_width_write = (caps >> 13) & 1;
 
 fixed_ctrl_mask = ~((1ull << (fixed_pmc_cnt * FIXED_CTR_CTRL_BITS)) - 1);
-if ( version == 2 )
-fixed_ctrl_mask |= 0x444;
+/* mask .AnyThread bits for all fixed counters */
+for( i = 0; i < fixed_pmc_cnt; i++ )
+   fixed_ctrl_mask |=
+   (FIXED_CTR_CTRL_ANYTHREAD_MASK << (FIXED_CTR_CTRL_BITS * i));
+
 fixed_counters_mask = ~((1ull << core2_get_bitwidth_fix_count()) - 1);
 global_ctrl_mask = ~1ULL << fixed_pmc_cnt) - 1) << 32) |
  ((1ULL << arch_pmc_cnt) - 1));
-- 
2.9.3


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH] arm64: xen: Implement EFI reset_system callback

2017-04-05 Thread Boris Ostrovsky
On 04/05/2017 02:14 PM, Julien Grall wrote:
> When rebooting DOM0 with ACPI, the kernel is crashing with the stack trace 
> [1].
>
> This is happening because when EFI runtimes are enabled, the reset code
> (see machin_restart) will first try to use EFI restart method.
>
> However, the EFI restart code is expecting the reset_system callback to
> be always set. This is not the case for Xen and will lead to crash.
>
> Looking at the reboot path, it is expected to fallback on an alternative
> reboot method if one does not work. So implement reset_system callback
> as a NOP for Xen.
>
> [   36.999270] reboot: Restarting system
> [   37.002921] Internal error: Attempting to execute userspace memory: 
> 8604 [#1] PREEMPT SMP
> [   37.011460] Modules linked in:
> [   37.014598] CPU: 0 PID: 1 Comm: systemd-shutdow Not tainted 
> 4.11.0-rc1-3-g1e248b60a39b-dirty #506
> [   37.023903] Hardware name: (null) (DT)
> [   37.027734] task: 800902068000 task.stack: 800902064000
> [   37.033739] PC is at 0x0
> [   37.036359] LR is at efi_reboot+0x94/0xd0
> [   37.040438] pc : [<>] lr : [] pstate: 
> 404001c5
> [   37.047920] sp : 800902067cf0
> [   37.051314] x29: 800902067cf0 x28: 800902068000
> [   37.056709] x27: 08992000 x26: 008e
> [   37.062104] x25: 0123 x24: 0015
> [   37.067499] x23:  x22: 08e6e250
> [   37.072894] x21: 08e6e000 x20: 
> [   37.078289] x19: 08e5d4c8 x18: 0010
> [   37.083684] x17: a7c27470 x16: deadbeef
> [   37.089079] x15: 0006 x14: 88f42bef
> [   37.094474] x13: 08f42bfd x12: 08e706c0
> [   37.099870] x11: 08e7 x10: 05f5e0ff
> [   37.105265] x9 : 800902067a50 x8 : 6974726174736552
> [   37.110660] x7 : 08cc6fb8 x6 : 08cc6fb0
> [   37.116055] x5 : 08c97dd8 x4 : 
> [   37.121453] x3 :  x2 : 
> [   37.126845] x1 :  x0 : 
> [   37.132239]
> [   37.133808] Process systemd-shutdow (pid: 1, stack limit = 
> 0x800902064000)
> [   37.141118] Stack: (0x800902067cf0 to 0x800902068000)
> [   37.146949] 7ce0:   800902067d40 
> 08085334
> [   37.154869] 7d00:  08f3b000 800902067d40 
> 080852e0
> [   37.162787] 7d20: 08cc6fb0 08cc6fb8 08c7f580 
> 08c97dd8
> [   37.170706] 7d40: 800902067d60 080e2c2c  
> 01234567
> [   37.178624] 7d60: 800902067d80 080e2ee8  
> 080e2df4
> [   37.186544] 7d80:  080830f0  
> 8008ff1c1000
> [   37.194462] 7da0:  a7c4b1cc  
> 0024
> [   37.202380] 7dc0: 800902067dd0 0005 f24743c8 
> 0004
> [   37.210299] 7de0: f2475f03 0010 f2474418 
> 0005
> [   37.218218] 7e00: f2474578 000a d6b722c0 
> 0001
> [   37.226136] 7e20: 0123 0038 800902067e50 
> 081e7294
> [   37.234055] 7e40: 800902067e60 081e935c 800902067e60 
> 081e9388
> [   37.241973] 7e60: 800902067eb0 081ea388  
> 8008ff1c1000
> [   37.249892] 7e80:  a7c4a79c  
> 0002
> [   37.257810] 7ea0: 0104   
> 080830f0
> [   37.265729] 7ec0: fee1dead 28121969 01234567 
> 
> [   37.273651] 7ee0:  80800080 80008080 
> feffa9a9d4ff2d66
> [   37.281567] 7f00: 008e feffa9a9d5b60e0f 7f7f7f7f 
> 0101010101010101
> [   37.289485] 7f20: 0010 0008 003a 
> a7ccf588
> [   37.297404] 7f40: d6b87d00 a7c4b1b0 f2474be0 
> d6b88000
> [   37.305326] 7f60: f2474fb0 01234567  
> 
> [   37.313240] 7f80:  0001 d6b70d4d 
> 
> [   37.321159] 7fa0: 0001 f2474ea0 d6b5e2e0 
> f2474e80
> [   37.329078] 7fc0: a7c4b1cc  fee1dead 
> 008e
> [   37.336997] 7fe0:   9ce839cffee77eab 
> fafdbf9f7ed57f2f
> [   37.344911] Call trace:
> [   37.347437] Exception stack(0x800902067b20 to 0x800902067c50)
> [   37.353970] 7b20: 08e5d4c8 0001 80f82000 
> 
> [   37.361883] 7b40: 800902067b60 08e17000 08f44c68 
> 0001081081b4
> [   37.369802] 7b60: 800902067bf0 08108478  
> 

[Xen-devel] [PATCH v3 09/13] qobject: Use simpler QDict/QList scalar insertion macros

2017-04-05 Thread Eric Blake
We now have macros in place to make it less verbose to add a scalar
to QDict and QList, so use them.  To make this patch smaller to
review, a couple of subdirectories were done in earlier patches.

Patch created mechanically via:
  spatch --sp-file scripts/coccinelle/qobject.cocci \
--macro-file scripts/cocci-macro-file.h --dir . --in-place
and needed only one touch-up in monitor.c to avoid a long line.

Signed-off-by: Eric Blake 
---
 block.c   | 45 +++--
 blockdev.c| 30 +-
 hw/block/xen_disk.c   |  2 +-
 hw/usb/xen-usb.c  | 12 ++--
 monitor.c | 23 +++
 qapi/qmp-event.c  |  2 +-
 qemu-img.c|  6 +++---
 qemu-io.c |  2 +-
 qemu-nbd.c|  2 +-
 qobject/qdict.c   |  2 +-
 target/s390x/cpu_models.c |  4 ++--
 util/qemu-option.c|  2 +-
 12 files changed, 60 insertions(+), 72 deletions(-)

diff --git a/block.c b/block.c
index 1803334..9b87bf6 100644
--- a/block.c
+++ b/block.c
@@ -937,16 +937,14 @@ static void update_flags_from_options(int *flags, 
QemuOpts *opts)
 static void update_options_from_flags(QDict *options, int flags)
 {
 if (!qdict_haskey(options, BDRV_OPT_CACHE_DIRECT)) {
-qdict_put(options, BDRV_OPT_CACHE_DIRECT,
-  qbool_from_bool(flags & BDRV_O_NOCACHE));
+qdict_put_bool(options, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
 }
 if (!qdict_haskey(options, BDRV_OPT_CACHE_NO_FLUSH)) {
-qdict_put(options, BDRV_OPT_CACHE_NO_FLUSH,
-  qbool_from_bool(flags & BDRV_O_NO_FLUSH));
+qdict_put_bool(options, BDRV_OPT_CACHE_NO_FLUSH,
+   flags & BDRV_O_NO_FLUSH);
 }
 if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
-qdict_put(options, BDRV_OPT_READ_ONLY,
-  qbool_from_bool(!(flags & BDRV_O_RDWR)));
+qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
 }
 }

@@ -1362,7 +1360,7 @@ static int bdrv_fill_options(QDict **options, const char 
*filename,
 /* Fetch the file name from the options QDict if necessary */
 if (protocol && filename) {
 if (!qdict_haskey(*options, "filename")) {
-qdict_put(*options, "filename", qstring_from_str(filename));
+qdict_put_str(*options, "filename", filename);
 parse_filename = true;
 } else {
 error_setg(errp, "Can't specify 'file' and 'filename' options at "
@@ -1383,7 +1381,7 @@ static int bdrv_fill_options(QDict **options, const char 
*filename,
 }

 drvname = drv->format_name;
-qdict_put(*options, "driver", qstring_from_str(drvname));
+qdict_put_str(*options, "driver", drvname);
 } else {
 error_setg(errp, "Must specify either driver or file");
 return -EINVAL;
@@ -2034,7 +2032,7 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict 
*parent_options,
 }

 if (bs->backing_format[0] != '\0' && !qdict_haskey(options, "driver")) {
-qdict_put(options, "driver", qstring_from_str(bs->backing_format));
+qdict_put_str(options, "driver", bs->backing_format);
 }

 backing_hd = bdrv_open_inherit(*backing_filename ? backing_filename : NULL,
@@ -2189,12 +2187,9 @@ static BlockDriverState 
*bdrv_append_temp_snapshot(BlockDriverState *bs,
 }

 /* Prepare options QDict for the temporary file */
-qdict_put(snapshot_options, "file.driver",
-  qstring_from_str("file"));
-qdict_put(snapshot_options, "file.filename",
-  qstring_from_str(tmp_filename));
-qdict_put(snapshot_options, "driver",
-  qstring_from_str("qcow2"));
+qdict_put_str(snapshot_options, "file.driver", "file");
+qdict_put_str(snapshot_options, "file.filename", tmp_filename);
+qdict_put_str(snapshot_options, "driver", "qcow2");

 bs_snapshot = bdrv_open(NULL, NULL, snapshot_options, flags, errp);
 snapshot_options = NULL;
@@ -2369,8 +2364,7 @@ static BlockDriverState *bdrv_open_inherit(const char 
*filename,
 goto fail;
 }

-qdict_put(options, "file",
-  qstring_from_str(bdrv_get_node_name(file_bs)));
+qdict_put_str(options, "file", bdrv_get_node_name(file_bs));
 }
 }

@@ -2392,8 +2386,8 @@ static BlockDriverState *bdrv_open_inherit(const char 
*filename,
  * sure to update both bs->options (which has the full effective
  * options for bs) and options (which has file.* already removed).
  */
-qdict_put(bs->options, "driver", qstring_from_str(drv->format_name));
-qdict_put(options, "driver", qstring_from_str(drv->format_name));
+qdict_put_str(bs->options, "driver", drv->format_name);
+qdict_put_str(options, "driver", drv->format_name);
 

[Xen-devel] [libvirt test] 107207: regressions - FAIL

2017-04-05 Thread osstest service owner
flight 107207 libvirt real [real]
http://logs.test-lab.xenproject.org/osstest/logs/107207/

Regressions :-(

Tests which did not succeed and are blocking,
including tests which could not be run:
 test-armhf-armhf-libvirt-xsm  6 xen-boot fail REGR. vs. 106829

Regressions which are regarded as allowable (not blocking):
 test-armhf-armhf-libvirt 13 saverestore-support-checkfail  like 106829
 test-armhf-armhf-libvirt-raw 12 saverestore-support-checkfail  like 106829

Tests which did not succeed, but are not blocking:
 test-arm64-arm64-libvirt-xsm  1 build-check(1)   blocked  n/a
 test-arm64-arm64-libvirt-qcow2  1 build-check(1)   blocked  n/a
 test-arm64-arm64-libvirt  1 build-check(1)   blocked  n/a
 build-arm64-pvops 5 kernel-build fail   never pass
 test-amd64-amd64-libvirt-xsm 12 migrate-support-checkfail   never pass
 test-amd64-i386-libvirt-xsm  12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt 12 migrate-support-checkfail   never pass
 test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm 10 migrate-support-check 
fail never pass
 test-armhf-armhf-libvirt 12 migrate-support-checkfail   never pass
 test-armhf-armhf-libvirt-raw 11 migrate-support-checkfail   never pass
 test-amd64-i386-libvirt  12 migrate-support-checkfail   never pass
 test-amd64-amd64-libvirt-vhd 11 migrate-support-checkfail   never pass

version targeted for testing:
 libvirt  2e8c60958ac32624296eee263bf34bb21a32360c
baseline version:
 libvirt  9b14b2bc3ba95457589fe08f139542476314ff19

Last test of basis   106829  2017-03-22 04:22:56 Z   14 days
Failing since106855  2017-03-23 04:22:59 Z   13 days   13 attempts
Testing same since   107207  2017-04-05 04:29:04 Z0 days1 attempts


People who touched revisions under test:
  Andrea Bolognani 
  Cédric Bosdonnat 
  Daniel Veillard 
  Dawid Zamirski 
  Eric Blake 
  Erik Skultety 
  Jiri Denemark 
  John Ferlan 
  Ján Tomko 
  Laine Stump 
  Martin Kletzander 
  Michal Privoznik 
  Nikolay Shirokovskiy 
  Peter Krempa 
  Roman Bogorodskiy 

jobs:
 build-amd64-xsm  pass
 build-arm64-xsm  pass
 build-armhf-xsm  pass
 build-i386-xsm   pass
 build-amd64  pass
 build-arm64  pass
 build-armhf  pass
 build-i386   pass
 build-amd64-libvirt  pass
 build-arm64-libvirt  pass
 build-armhf-libvirt  pass
 build-i386-libvirt   pass
 build-amd64-pvopspass
 build-arm64-pvopsfail
 build-armhf-pvopspass
 build-i386-pvops pass
 test-amd64-amd64-libvirt-qemuu-debianhvm-amd64-xsm   pass
 test-amd64-i386-libvirt-qemuu-debianhvm-amd64-xsmpass
 test-amd64-amd64-libvirt-xsm pass
 test-arm64-arm64-libvirt-xsm blocked 
 test-armhf-armhf-libvirt-xsm fail
 test-amd64-i386-libvirt-xsm  pass
 test-amd64-amd64-libvirt pass
 test-arm64-arm64-libvirt blocked 
 test-armhf-armhf-libvirt pass
 test-amd64-i386-libvirt  pass
 test-amd64-amd64-libvirt-pairpass
 test-amd64-i386-libvirt-pair pass
 test-arm64-arm64-libvirt-qcow2   blocked 
 test-armhf-armhf-libvirt-raw pass
 test-amd64-amd64-libvirt-vhd pass



sg-report-flight on 

Re: [Xen-devel] [PATCH v4 00/19] Provide a command line option to choose how to handle SErrors

2017-04-05 Thread Stefano Stabellini
Thank you Wei. I committed this series. I fixed on commit patch #16 that
has 2 asserts.

On Wed, 5 Apr 2017, Wei Chen wrote:
> From XSA-201, we know that, a guest could trigger SErrors when accessing
> memory mapped HW in a non-conventional way. In the patches for XSA-201,
> we crash the guest when we captured such asynchronous aborts to avoid data
> corruption.
> 
> In order to distinguish guest-generated SErrors from hypervisor-generated
> SErrors. We have to place SError checking code in every EL1 -> EL2 paths.
> That will be an overhead on entries caused by dsb/isb.
> 
> But not all platforms want to categorize the SErrors. For example, a host
> that is running with trusted guests. The administrator can confirm that
> all guests that are running on the host will not trigger such SErrors. In
> this user scene, we should provide some options to administrator to avoid
> categorizing the SErrors. And then reduce the overhead of dsb/isb.
> 
> We provided following 3 options to administrator to determine how to handle
> the SErrors:
> 
> * `diverse`:
>   The hypervisor will distinguish guest SErrors from hypervisor SErrors.
>   The guest generated SErrors will be forwarded to guests, the hypervisor
>   generated SErrors will cause the whole system crash.
>   It requires:
>   1. Place dsb/isb on all EL1 -> EL2 trap entries to categorize SErrors
>  correctly.
>   2. Place dsb/isb on EL2 -> EL1 return paths to prevent slipping hypervisor
>  SErrors to guests.
>   3. Place dsb/isb in context switch to isolate the SErrors between 2 vCPUs.
> 
> * `forward`:
>   The hypervisor will not distinguish guest SErrors from hypervisor SErrors.
>   All SErrors will be forwarded to guests, except the SErrors generated when
>   idle vCPU is running. The idle domain doesn't have the ability to hanle the
>   SErrors, so we have to crash the whole system when we get SErros with idle
>   vCPU. This option will avoid most overhead of the dsb/isb, except the 
> dsb/isb
>   in context switch which is used to isolate the SErrors between 2 vCPUs.
> 
> * `panic`:
>   The hypervisor will not distinguish guest SErrors from hypervisor SErrors.
>   All SErrors will crash the whole system. This option will avoid all overhead
>   of the dsb/isb
> 
> ---
> v3->v4:
> 1. Rename SKIP_CHECK_PENDING_VSERROR to SKIP_SYNCHRONIZE_SERROR_ENTRY_EXIT.
> 2. Add ASSERT in SYNCHRONIZING_SERROR macro to ensure abort is enabled.
> 3. Use one local_abort_is_enabled for ARM32 and ARM64.
> 4. Fix some grammer issues.
> 5. Add Reviewed-by tags from Julien and Stefano for most of this series.
> 
> Wei Chen (19):
>   xen/arm: Save ESR_EL2 to avoid using mismatched value in syndrome
> check
>   xen/arm: Introduce a helper to get default HCR_EL2 flags
>   xen/arm: Set and restore HCR_EL2 register for each vCPU separately
>   xen/arm: Avoid setting/clearing HCR_RW at every context switch
>   xen/arm: Save HCR_EL2 when a guest took the SError
>   xen/arm: Introduce a virtual abort injection helper
>   xen/arm: Introduce a command line parameter for SErrors/Aborts
>   xen/arm: Introduce a initcall to update cpu_hwcaps by serror_op
>   xen/arm64: Use alternative to skip the check of pending serrors
>   xen/arm32: Use alternative to skip the check of pending serrors
>   xen/arm: Move macro VABORT_GEN_BY_GUEST to common header
>   xen/arm: Introduce new helpers to handle guest/hyp SErrors
>   xen/arm: Replace do_trap_guest_serror with new helpers
>   xen/arm: Unmask the Abort/SError bit in the exception entries
>   xen/arm: Introduce a helper to check local abort is enabled
>   xen/arm: Introduce a macro to synchronize SError
>   xen/arm: Isolate the SError between the context switch of 2 vCPUs
>   xen/arm: Prevent slipping hypervisor SError to guest
>   xen/arm: Handle guest external abort as guest SError
> 
>  docs/misc/xen-command-line.markdown   |  44 
>  xen/arch/arm/arm32/asm-offsets.c  |   1 +
>  xen/arch/arm/arm32/entry.S|  28 -
>  xen/arch/arm/arm32/traps.c|   5 +-
>  xen/arch/arm/arm64/asm-offsets.c  |   1 +
>  xen/arch/arm/arm64/domctl.c   |   6 ++
>  xen/arch/arm/arm64/entry.S| 105 +--
>  xen/arch/arm/arm64/traps.c|   2 +-
>  xen/arch/arm/domain.c |  19 
>  xen/arch/arm/domain_build.c   |   7 ++
>  xen/arch/arm/p2m.c|  10 +-
>  xen/arch/arm/traps.c  | 187 
> +-
>  xen/include/asm-arm/arm32/processor.h |  12 +--
>  xen/include/asm-arm/arm64/processor.h |   3 +-
>  xen/include/asm-arm/cpufeature.h  |   4 +-
>  xen/include/asm-arm/domain.h  |   4 +
>  xen/include/asm-arm/processor.h   |  30 +-
>  xen/include/asm-arm/system.h  |   7 ++
>  18 files changed, 364 insertions(+), 111 deletions(-)
> 
> -- 
> 2.7.4
> 
> 
> ___
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> 

[Xen-devel] [PATCH v7 6/7] xen/9pfs: receive responses

2017-04-05 Thread Stefano Stabellini
Upon receiving a notification from the backend, schedule the
p9_xen_response work_struct. p9_xen_response checks if any responses are
available, if so, it reads them one by one, calling p9_client_cb to send
them up to the 9p layer (p9_client_cb completes the request). Handle the
ring following the Xen 9pfs specification.

Signed-off-by: Stefano Stabellini 
Reviewed-by: Boris Ostrovsky 
Reviewed-by: Juergen Gross 
CC: gr...@kaod.org
CC: jgr...@suse.com
CC: Eric Van Hensbergen 
CC: Ron Minnich 
CC: Latchesar Ionkov 
CC: v9fs-develo...@lists.sourceforge.net
---
 net/9p/trans_xen.c | 56 ++
 1 file changed, 56 insertions(+)

diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
index 28f30f4..4786424 100644
--- a/net/9p/trans_xen.c
+++ b/net/9p/trans_xen.c
@@ -189,6 +189,62 @@ static int p9_xen_request(struct p9_client *client, struct 
p9_req_t *p9_req)
 
 static void p9_xen_response(struct work_struct *work)
 {
+   struct xen_9pfs_front_priv *priv;
+   struct xen_9pfs_dataring *ring;
+   RING_IDX cons, prod, masked_cons, masked_prod;
+   struct xen_9pfs_header h;
+   struct p9_req_t *req;
+   int status;
+
+   ring = container_of(work, struct xen_9pfs_dataring, work);
+   priv = ring->priv;
+
+   while (1) {
+   cons = ring->intf->in_cons;
+   prod = ring->intf->in_prod;
+   virt_rmb();
+
+   if (xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) <
+   sizeof(h)) {
+   notify_remote_via_irq(ring->irq);
+   return;
+   }
+
+   masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
+   masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
+
+   /* First, read just the header */
+   xen_9pfs_read_packet(, ring->data.in, sizeof(h),
+masked_prod, _cons,
+XEN_9PFS_RING_SIZE);
+
+   req = p9_tag_lookup(priv->client, h.tag);
+   if (!req || req->status != REQ_STATUS_SENT) {
+   dev_warn(>dev->dev, "Wrong req tag=%x\n", h.tag);
+   cons += h.size;
+   virt_mb();
+   ring->intf->in_cons = cons;
+   continue;
+   }
+
+   memcpy(req->rc, , sizeof(h));
+   req->rc->offset = 0;
+
+   masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
+   /* Then, read the whole packet (including the header) */
+   xen_9pfs_read_packet(req->rc->sdata, ring->data.in, h.size,
+masked_prod, _cons,
+XEN_9PFS_RING_SIZE);
+
+   virt_mb();
+   cons += h.size;
+   ring->intf->in_cons = cons;
+
+   status = (req->status != REQ_STATUS_ERROR) ?
+   REQ_STATUS_RCVD : REQ_STATUS_ERROR;
+
+   p9_client_cb(priv->client, req, status);
+   }
 }
 
 static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r)
-- 
1.9.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v7 4/7] xen/9pfs: connect to the backend

2017-04-05 Thread Stefano Stabellini
Implement functions to handle the xenbus handshake. Upon connection,
allocate the rings according to the protocol specification.

Initialize a work_struct and a wait_queue. The work_struct will be used
to schedule work upon receiving an event channel notification from the
backend. The wait_queue will be used to wait when the ring is full and
we need to send a new request.

Signed-off-by: Stefano Stabellini 
Reviewed-by: Juergen Gross 
CC: gr...@kaod.org
CC: boris.ostrov...@oracle.com
CC: jgr...@suse.com
CC: Eric Van Hensbergen 
CC: Ron Minnich 
CC: Latchesar Ionkov 
CC: v9fs-develo...@lists.sourceforge.net
---
 net/9p/trans_xen.c | 281 +
 1 file changed, 281 insertions(+)

diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
index 3d07260..fe3d172 100644
--- a/net/9p/trans_xen.c
+++ b/net/9p/trans_xen.c
@@ -37,10 +37,54 @@
 #include 
 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
 
+#define XEN_9PFS_NUM_RINGS 2
+#define XEN_9PFS_RING_ORDER 6
+#define XEN_9PFS_RING_SIZE  XEN_FLEX_RING_SIZE(XEN_9PFS_RING_ORDER)
+
+struct xen_9pfs_header {
+   uint32_t size;
+   uint8_t id;
+   uint16_t tag;
+
+   /* uint8_t sdata[]; */
+} __attribute__((packed));
+
+/* One per ring, more than one per 9pfs share */
+struct xen_9pfs_dataring {
+   struct xen_9pfs_front_priv *priv;
+
+   struct xen_9pfs_data_intf *intf;
+   grant_ref_t ref;
+   int evtchn;
+   int irq;
+   /* protect a ring from concurrent accesses */
+   spinlock_t lock;
+
+   struct xen_9pfs_data data;
+   wait_queue_head_t wq;
+   struct work_struct work;
+};
+
+/* One per 9pfs share */
+struct xen_9pfs_front_priv {
+   struct list_head list;
+   struct xenbus_device *dev;
+   char *tag;
+   struct p9_client *client;
+
+   int num_rings;
+   struct xen_9pfs_dataring *rings;
+};
+
+static LIST_HEAD(xen_9pfs_devs);
+static DEFINE_RWLOCK(xen_9pfs_lock);
+
 static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
 {
return 0;
@@ -60,6 +104,25 @@ static int p9_xen_request(struct p9_client *client, struct 
p9_req_t *p9_req)
return 0;
 }
 
+static void p9_xen_response(struct work_struct *work)
+{
+}
+
+static irqreturn_t xen_9pfs_front_event_handler(int irq, void *r)
+{
+   struct xen_9pfs_dataring *ring = r;
+
+   if (!ring || !ring->priv->client) {
+   /* ignore spurious interrupt */
+   return IRQ_HANDLED;
+   }
+
+   wake_up_interruptible(>wq);
+   schedule_work(>work);
+
+   return IRQ_HANDLED;
+}
+
 static struct p9_trans_module p9_xen_trans = {
.name = "xen",
.maxsize = 1 << (XEN_9PFS_RING_ORDER + XEN_PAGE_SHIFT),
@@ -76,25 +139,243 @@ static int p9_xen_request(struct p9_client *client, 
struct p9_req_t *p9_req)
{ "" }
 };
 
+static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
+{
+   int i, j;
+
+   write_lock(_9pfs_lock);
+   list_del(>list);
+   write_unlock(_9pfs_lock);
+
+   for (i = 0; i < priv->num_rings; i++) {
+   if (!priv->rings[i].intf)
+   break;
+   if (priv->rings[i].irq > 0)
+   unbind_from_irqhandler(priv->rings[i].irq, priv->dev);
+   if (priv->rings[i].data.in) {
+   for (j = 0; j < (1 << XEN_9PFS_RING_ORDER); j++) {
+   grant_ref_t ref;
+
+   ref = priv->rings[i].intf->ref[j];
+   gnttab_end_foreign_access(ref, 0, 0);
+   }
+   free_pages((unsigned long)priv->rings[i].data.in,
+  XEN_9PFS_RING_ORDER -
+  (PAGE_SHIFT - XEN_PAGE_SHIFT));
+   }
+   gnttab_end_foreign_access(priv->rings[i].ref, 0, 0);
+   free_page((unsigned long)priv->rings[i].intf);
+   }
+   kfree(priv->rings);
+   kfree(priv->tag);
+   kfree(priv);
+}
+
 static int xen_9pfs_front_remove(struct xenbus_device *dev)
 {
+   struct xen_9pfs_front_priv *priv = dev_get_drvdata(>dev);
+
+   dev_set_drvdata(>dev, NULL);
+   xen_9pfs_front_free(priv);
return 0;
 }
 
+static int xen_9pfs_front_alloc_dataring(struct xenbus_device *dev,
+struct xen_9pfs_dataring *ring)
+{
+   int i = 0;
+   int ret = -ENOMEM;
+   void *bytes = NULL;
+
+   init_waitqueue_head(>wq);
+   spin_lock_init(>lock);
+   INIT_WORK(>work, p9_xen_response);
+
+   ring->intf = (struct xen_9pfs_data_intf *)get_zeroed_page(GFP_KERNEL);
+   if (!ring->intf)
+   return ret;
+   ret = gnttab_grant_foreign_access(dev->otherend_id,
+ virt_to_gfn(ring->intf), 0);
+ 

[Xen-devel] [PATCH v7 0/7] Xen transport for 9pfs frontend driver

2017-04-05 Thread Stefano Stabellini
Hi all,

This patch series implements a new transport for 9pfs, aimed at Xen
systems.

The transport is based on a traditional Xen frontend and backend drivers
pair. This patch series implements the frontend, which typically runs in
a regular unprivileged guest.

I also sent a series that implements the backend in userspace in QEMU,
which typically runs in Dom0 (but could also run in a another guest).

The frontend complies to the Xen transport for 9pfs specification
version 1, available here:

https://xenbits.xen.org/docs/unstable/misc/9pfs.html


The new Xen ring macros pulled in Linux in the first patch of the series
have been committed upstream in Xen, so there is nothing holding back
this series any longer. It could be considered for 4.12 or 4.13. It
should probably go via the Xen tree.


Changes in v7:
- merging the final version of the macros (Xen upstream commit
  f000908276382e1c0a3de359f9bbc7ba83999119)
- fixup argument ordering of the ring/write_packet macros callers

Changes in v6:
- add reviewd-bys
- fix error paths
- make p9_xen_write_todo return bool

Changes in v5:
- test priv->tag instead of ret
- run checkpatch.pl against the whole series, fix all issues
- set intf->ring_order appropriately
- use shorter link to 9pfs spec

Changes in v4:
- code style improvements
- use xenbus_read_unsigned when possible
- do not leak "versions"
- introduce BUILD_BUG_ON
- introduce rwlock to protect the xen_9pfs_devs list
- add review-by

Changes in v3:
- add full copyright header to trans_xen.c
- rename ring->ring to ring->data
- handle gnttab_grant_foreign_access errors
- remove ring->bytes
- wrap long lines
- add reviewed-by

Changes in v2:
- use XEN_PAGE_SHIFT instead of PAGE_SHIFT
- remove unnecessary initializations
- fix error paths
- fix memory allocations for 64K kernels
- simplify p9_xen_create and p9_xen_close
- use virt_XXX barriers
- set status = REQ_STATUS_ERROR inside the p9_xen_response loop
- add in-code comments


Stefano Stabellini (7):
  xen: import new ring macros in ring.h
  xen: introduce the header file for the Xen 9pfs transport protocol
  xen/9pfs: introduce Xen 9pfs transport driver
  xen/9pfs: connect to the backend
  xen/9pfs: send requests to the backend
  xen/9pfs: receive responses
  xen/9pfs: build 9pfs Xen transport driver

 include/xen/interface/io/9pfs.h |  36 +++
 include/xen/interface/io/ring.h | 143 +++
 net/9p/Kconfig  |   8 +
 net/9p/Makefile |   4 +
 net/9p/trans_xen.c  | 545 
 5 files changed, 736 insertions(+)
 create mode 100644 include/xen/interface/io/9pfs.h
 create mode 100644 net/9p/trans_xen.c

Cheers,

Stefano

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v7 2/7] xen: introduce the header file for the Xen 9pfs transport protocol

2017-04-05 Thread Stefano Stabellini
It uses the new ring.h macros to declare rings and interfaces.

Signed-off-by: Stefano Stabellini 
CC: konrad.w...@oracle.com
CC: boris.ostrov...@oracle.com
CC: jgr...@suse.com
CC: gr...@kaod.org
---
 include/xen/interface/io/9pfs.h | 36 
 1 file changed, 36 insertions(+)
 create mode 100644 include/xen/interface/io/9pfs.h

diff --git a/include/xen/interface/io/9pfs.h b/include/xen/interface/io/9pfs.h
new file mode 100644
index 000..5b6c19d
--- /dev/null
+++ b/include/xen/interface/io/9pfs.h
@@ -0,0 +1,36 @@
+/*
+ * 9pfs.h -- Xen 9PFS transport
+ *
+ * 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) 2017 Stefano Stabellini 
+ */
+
+#ifndef __XEN_PUBLIC_IO_9PFS_H__
+#define __XEN_PUBLIC_IO_9PFS_H__
+
+#include "xen/interface/io/ring.h"
+
+/*
+ * See docs/misc/9pfs.markdown in xen.git for the full specification:
+ * https://xenbits.xen.org/docs/unstable/misc/9pfs.html
+ */
+DEFINE_XEN_FLEX_RING_AND_INTF(xen_9pfs);
+
+#endif
-- 
1.9.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v7 5/7] xen/9pfs: send requests to the backend

2017-04-05 Thread Stefano Stabellini
Implement struct p9_trans_module create and close functions by looking
at the available Xen 9pfs frontend-backend connections. We don't expect
many frontend-backend connections, thus walking a list is OK.

Send requests to the backend by copying each request to one of the
available rings (each frontend-backend connection comes with multiple
rings). Handle the ring and notifications following the 9pfs
specification. If there are not enough free bytes on the ring for the
request, wait on the wait_queue: the backend will send a notification
after consuming more requests.

Signed-off-by: Stefano Stabellini 
Reviewed-by: Boris Ostrovsky 
Reviewed-by: Juergen Gross 
CC: gr...@kaod.org
CC: jgr...@suse.com
CC: Eric Van Hensbergen 
CC: Ron Minnich 
CC: Latchesar Ionkov 
CC: v9fs-develo...@lists.sourceforge.net
---
 net/9p/trans_xen.c | 87 --
 1 file changed, 85 insertions(+), 2 deletions(-)

diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
index fe3d172..28f30f4 100644
--- a/net/9p/trans_xen.c
+++ b/net/9p/trans_xen.c
@@ -85,22 +85,105 @@ struct xen_9pfs_front_priv {
 static LIST_HEAD(xen_9pfs_devs);
 static DEFINE_RWLOCK(xen_9pfs_lock);
 
+/* We don't currently allow canceling of requests */
 static int p9_xen_cancel(struct p9_client *client, struct p9_req_t *req)
 {
-   return 0;
+   return 1;
 }
 
 static int p9_xen_create(struct p9_client *client, const char *addr, char 
*args)
 {
-   return 0;
+   struct xen_9pfs_front_priv *priv;
+
+   read_lock(_9pfs_lock);
+   list_for_each_entry(priv, _9pfs_devs, list) {
+   if (!strcmp(priv->tag, addr)) {
+   priv->client = client;
+   read_unlock(_9pfs_lock);
+   return 0;
+   }
+   }
+   read_unlock(_9pfs_lock);
+   return -EINVAL;
 }
 
 static void p9_xen_close(struct p9_client *client)
 {
+   struct xen_9pfs_front_priv *priv;
+
+   read_lock(_9pfs_lock);
+   list_for_each_entry(priv, _9pfs_devs, list) {
+   if (priv->client == client) {
+   priv->client = NULL;
+   read_unlock(_9pfs_lock);
+   return;
+   }
+   }
+   read_unlock(_9pfs_lock);
+}
+
+static bool p9_xen_write_todo(struct xen_9pfs_dataring *ring, RING_IDX size)
+{
+   RING_IDX cons, prod;
+
+   cons = ring->intf->out_cons;
+   prod = ring->intf->out_prod;
+   virt_mb();
+
+   return XEN_9PFS_RING_SIZE -
+   xen_9pfs_queued(prod, cons, XEN_9PFS_RING_SIZE) >= size;
 }
 
 static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
 {
+   struct xen_9pfs_front_priv *priv = NULL;
+   RING_IDX cons, prod, masked_cons, masked_prod;
+   unsigned long flags;
+   u32 size = p9_req->tc->size;
+   struct xen_9pfs_dataring *ring;
+   int num;
+
+   read_lock(_9pfs_lock);
+   list_for_each_entry(priv, _9pfs_devs, list) {
+   if (priv->client == client)
+   break;
+   }
+   read_unlock(_9pfs_lock);
+   if (!priv || priv->client != client)
+   return -EINVAL;
+
+   num = p9_req->tc->tag % priv->num_rings;
+   ring = >rings[num];
+
+again:
+   while (wait_event_interruptible(ring->wq,
+   p9_xen_write_todo(ring, size)) != 0)
+   ;
+
+   spin_lock_irqsave(>lock, flags);
+   cons = ring->intf->out_cons;
+   prod = ring->intf->out_prod;
+   virt_mb();
+
+   if (XEN_9PFS_RING_SIZE - xen_9pfs_queued(prod, cons,
+XEN_9PFS_RING_SIZE) < size) {
+   spin_unlock_irqrestore(>lock, flags);
+   goto again;
+   }
+
+   masked_prod = xen_9pfs_mask(prod, XEN_9PFS_RING_SIZE);
+   masked_cons = xen_9pfs_mask(cons, XEN_9PFS_RING_SIZE);
+
+   xen_9pfs_write_packet(ring->data.out, p9_req->tc->sdata, size,
+ _prod, masked_cons, XEN_9PFS_RING_SIZE);
+
+   p9_req->status = REQ_STATUS_SENT;
+   virt_wmb(); /* write ring before updating pointer */
+   prod += size;
+   ring->intf->out_prod = prod;
+   spin_unlock_irqrestore(>lock, flags);
+   notify_remote_via_irq(ring->irq);
+
return 0;
 }
 
-- 
1.9.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v7 7/7] xen/9pfs: build 9pfs Xen transport driver

2017-04-05 Thread Stefano Stabellini
This patch adds a Kconfig option and Makefile support for building the
9pfs Xen driver.

Signed-off-by: Stefano Stabellini 
Reviewed-by: Juergen Gross 
CC: gr...@kaod.org
CC: boris.ostrov...@oracle.com
CC: jgr...@suse.com
CC: Eric Van Hensbergen 
CC: Ron Minnich 
CC: Latchesar Ionkov 
CC: v9fs-develo...@lists.sourceforge.net
---
 net/9p/Kconfig  | 8 
 net/9p/Makefile | 4 
 2 files changed, 12 insertions(+)

diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index a75174a..3f286f1 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -22,6 +22,14 @@ config NET_9P_VIRTIO
  This builds support for a transports between
  guest partitions and a host partition.
 
+config NET_9P_XEN
+   depends on XEN
+   tristate "9P Xen Transport"
+   help
+ This builds support for a transport for 9pfs between
+ two Xen domains.
+
+
 config NET_9P_RDMA
depends on INET && INFINIBAND && INFINIBAND_ADDR_TRANS
tristate "9P RDMA Transport (Experimental)"
diff --git a/net/9p/Makefile b/net/9p/Makefile
index a0874cc..697ea7c 100644
--- a/net/9p/Makefile
+++ b/net/9p/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_NET_9P) := 9pnet.o
+obj-$(CONFIG_NET_9P_XEN) += 9pnet_xen.o
 obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o
 obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
 
@@ -14,5 +15,8 @@ obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
 9pnet_virtio-objs := \
trans_virtio.o \
 
+9pnet_xen-objs := \
+   trans_xen.o \
+
 9pnet_rdma-objs := \
trans_rdma.o \
-- 
1.9.1


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v7 1/7] xen: import new ring macros in ring.h

2017-04-05 Thread Stefano Stabellini
Sync the ring.h file with upstream Xen, to introduce the new ring macros.
They will be used by the Xen transport for 9pfs.

Signed-off-by: Stefano Stabellini 
CC: konrad.w...@oracle.com
CC: boris.ostrov...@oracle.com
CC: jgr...@suse.com
CC: gr...@kaod.org

---
NB: The new macros have been committed to Xen. It is OK to apply this
patch now.
---
---
 include/xen/interface/io/ring.h | 143 
 1 file changed, 143 insertions(+)

diff --git a/include/xen/interface/io/ring.h b/include/xen/interface/io/ring.h
index 21f4fbd..c794568 100644
--- a/include/xen/interface/io/ring.h
+++ b/include/xen/interface/io/ring.h
@@ -283,4 +283,147 @@ struct __name##_back_ring {   
\
 (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
 } while (0)
 
+
+/*
+ * DEFINE_XEN_FLEX_RING_AND_INTF defines two monodirectional rings and
+ * functions to check if there is data on the ring, and to read and
+ * write to them.
+ *
+ * DEFINE_XEN_FLEX_RING is similar to DEFINE_XEN_FLEX_RING_AND_INTF, but
+ * does not define the indexes page. As different protocols can have
+ * extensions to the basic format, this macro allow them to define their
+ * own struct.
+ *
+ * XEN_FLEX_RING_SIZE
+ *   Convenience macro to calculate the size of one of the two rings
+ *   from the overall order.
+ *
+ * $NAME_mask
+ *   Function to apply the size mask to an index, to reduce the index
+ *   within the range [0-size].
+ *
+ * $NAME_read_packet
+ *   Function to read data from the ring. The amount of data to read is
+ *   specified by the "size" argument.
+ *
+ * $NAME_write_packet
+ *   Function to write data to the ring. The amount of data to write is
+ *   specified by the "size" argument.
+ *
+ * $NAME_get_ring_ptr
+ *   Convenience function that returns a pointer to read/write to the
+ *   ring at the right location.
+ *
+ * $NAME_data_intf
+ *   Indexes page, shared between frontend and backend. It also
+ *   contains the array of grant refs.
+ *
+ * $NAME_queued
+ *   Function to calculate how many bytes are currently on the ring,
+ *   ready to be read. It can also be used to calculate how much free
+ *   space is currently on the ring (XEN_FLEX_RING_SIZE() -
+ *   $NAME_queued()).
+ */
+
+#ifndef XEN_PAGE_SHIFT
+/* The PAGE_SIZE for ring protocols and hypercall interfaces is always
+ * 4K, regardless of the architecture, and page granularity chosen by
+ * operating systems.
+ */
+#define XEN_PAGE_SHIFT 12
+#endif
+#define XEN_FLEX_RING_SIZE(order) \
+(1UL << ((order) + XEN_PAGE_SHIFT - 1))
+
+#define DEFINE_XEN_FLEX_RING(name)\
+static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size)  \
+{ \
+return idx & (ring_size - 1); \
+} \
+  \
+static inline unsigned char *name##_get_ring_ptr(unsigned char *buf,  \
+ RING_IDX idx,\
+ RING_IDX ring_size)  \
+{ \
+return buf + name##_mask(idx, ring_size); \
+} \
+  \
+static inline void name##_read_packet(void *opaque,   \
+  const unsigned char *buf,   \
+  size_t size,\
+  RING_IDX masked_prod,   \
+  RING_IDX *masked_cons,  \
+  RING_IDX ring_size) \
+{ \
+if (*masked_cons < masked_prod || \
+size <= ring_size - *masked_cons) {   \
+memcpy(opaque, buf + *masked_cons, size); \
+} else {  \
+memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons); \
+memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf,   \
+   size - (ring_size - *masked_cons));\
+} \
+*masked_cons = name##_mask(*masked_cons + size, ring_size);  

Re: [Xen-devel] [PATCH v2 for-4.9 4/6] x86/svm: Introduce svm_emul_swint_injection()

2017-04-05 Thread Andrew Cooper
On 05/04/17 19:58, Boris Ostrovsky wrote:
> On 04/05/2017 01:33 PM, Andrew Cooper wrote:
>> Software events require emulation in some cases on AMD hardware.  Introduce
>> svm_emul_swint_injection() to perform this emulation if necessary in
>> svm_inject_event(), which will cope with any sources of event, rather than
>> just those coming from x86_emulate().
>>
>> This logic mirrors inject_swint() in the x86 instruction emulator.
>>
>> Signed-off-by: Andrew Cooper 
>
>> +/*
>> + * Read all 8/16 bytes so the idtr limit check is applied properly to
>> + * this entry, even though we don't look all the words read.
>> + */
> ("don't look *at* all the words read"? )
>
> Reviewed-by: Boris Ostrovsky 

Oops yes - will fix.

~Andrew

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v2 for-4.9 4/6] x86/svm: Introduce svm_emul_swint_injection()

2017-04-05 Thread Boris Ostrovsky
On 04/05/2017 01:33 PM, Andrew Cooper wrote:
> Software events require emulation in some cases on AMD hardware.  Introduce
> svm_emul_swint_injection() to perform this emulation if necessary in
> svm_inject_event(), which will cope with any sources of event, rather than
> just those coming from x86_emulate().
>
> This logic mirrors inject_swint() in the x86 instruction emulator.
>
> Signed-off-by: Andrew Cooper 


> +/*
> + * Read all 8/16 bytes so the idtr limit check is applied properly to
> + * this entry, even though we don't look all the words read.
> + */

("don't look *at* all the words read"? )

Reviewed-by: Boris Ostrovsky 



___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v2 for-4.9 2/6] x86/hvm: Correct long mode predicate

2017-04-05 Thread Boris Ostrovsky
On 04/05/2017 01:33 PM, Andrew Cooper wrote:
> hvm_long_mode_enabled() tests for EFER.LMA, which is specifically different to
> EFER.LME.
>
> Rename it to match its behaviour, and have it strictly return a boolean value
> (although all its callers already use it in implicitly-boolean contexts, so no
> functional change).

Reviewed-by: Boris Ostrovsky 


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH V2] libxc: fix xc_translate_foreign_address()

2017-04-05 Thread Julien Grall



On 05/04/17 16:03, Wei Liu wrote:

On Wed, Apr 05, 2017 at 03:58:05PM +0100, Julien Grall wrote:

Hi Razvan,

On 05/04/17 15:53, Razvan Cojocaru wrote:

Currently xc_translate_foreign_address() only checks for the PSE bit on
level 2 entries (that's 2 MB pages on x64 and 32-bit with PAE, and 4 MB
pages on 32-bit). But the Linux kernel sometimes uses 1 GB pages. This
patch fixes that, by checking the PSE bit on level 3 entries if the guest
has 4 translation levels (that means 64-bit guests only).

Signed-off-by: Cristian-Bogdan Sirb 


He is the author of the patch, correct? If so, he should be the author as
well (e.g From: ...).

Also, you may want to add your signed-off-by here.



Julien, if you agree to let this patch go in 4.9. I can fix those up.


Release-acked-by: Julien Grall 

Cheers,



Razvan, please tell me what you want me to do.

Code-wise:

Acked-by: Wei Liu 



Cheers,


---
Changes since V1:
 - Added header comment.
---
 tools/libxc/include/xenctrl.h | 3 +++
 tools/libxc/xc_pagetab.c  | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 2d97d36..ca4bb6c 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1460,6 +1460,9 @@ int xc_lockprof_query(xc_interface *xch,
 void *xc_memalign(xc_interface *xch, size_t alignment, size_t size);

 /**
+ * Avoid using this function, as it does not work for all cases (such
+ * as 4M superpages, or guests using PSE36). Only used for debugging.
+ *
  * Translates a virtual address in the context of a given domain and
  * vcpu returning the GFN containing the address (that is, an MFN for
  * PV guests, a PFN for HVM guests).  Returns 0 for failure.
diff --git a/tools/libxc/xc_pagetab.c b/tools/libxc/xc_pagetab.c
index 92eebd6..db25c20 100644
--- a/tools/libxc/xc_pagetab.c
+++ b/tools/libxc/xc_pagetab.c
@@ -93,7 +93,7 @@ unsigned long xc_translate_foreign_address(xc_interface *xch, 
uint32_t dom,
 return 0;
 }
 paddr = pte & 0x000ff000ull;
-if (level == 2 && (pte & PTE_PSE)) {
+if ((level == 2 || (level == 3 && pt_levels == 4)) && (pte & PTE_PSE)) 
{
 mask = ((mask ^ ~-mask) >> 1); /* All bits below first set bit */
 return ((paddr & ~mask) | (virt & mask)) >> PAGE_SHIFT;
 }



--
Julien Grall


--
Julien Grall

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [Outreachy] Doubts regarding setup, git version and selection of micro task

2017-04-05 Thread Stefano Stabellini
On Wed, 5 Apr 2017, Julien Grall wrote:
> (CC Lars)
> 
> Hi,
> 
> On 05/04/17 12:51, Wei Liu wrote:
> > On Wed, Apr 05, 2017 at 05:04:00PM +0530, Tejaswini Poluri wrote:
> > > Hi Stefano and Julien,
> > > 
> > > This is Tejaswini. I had been working as a Senior Software developer in
> > > Samsung and Cavium networks in linux kernel domain previously. I took a
> > > break for one year for personal reasons. I am looking forward to restart
> > > my
> > > career as a Linux engineer again with outreachy 2017 internships. I have
> > > experience of working with device trees and virtual filesystems.
> 
> Thank you for your interest on the project.
> 
> I think the deadline for Outreachy has been extended to 13th of April. You
> would need to fill out an application (see
> https://wiki.xenproject.org/wiki/Outreachy/Apply).

Indeed. Also see the following page (it says GSoC at the top but applies
to Outreachy too):

https://wiki.xenproject.org/wiki/GSoC_Student_Application_Template

Please add as many details as you can to the "Implementation Plan".


> > > Hence, I found the following projects
> > >  of
> > > Xen-hypervisor very interesting:
> > > 1. Xen on ARM: create multiple guests from device tree
> > > 2. Share a page in memory from the VM config file
> > > 
> > > I have an intel i5 laptop already running both windows 10 + ubuntu 16.04.
> > > I
> > > was looking at Nested virtualization
> > >  option to
> > > build and test Xen. Would this work for these projects?
> > > 
> > 
> > Won't work for ARM projects.
> 
> The second project (Share a page in memory from VM config file) could be done
> on both x86 and ARM.
> 
> The first will be ARM specific. For that you can either use the real hardware
> such as the cubieboard or use the foundation model provided freely by ARM (see
> [1]).

Given that we have two other applicants for the "Share a page in memory
from the VM config file", I encourage you to apply for "Xen on ARM:
create multiple guests from device tree". I wrote more details on this
project here: http://marc.info/?l=xen-devel=149074542307880

Don't worry about ARM hardware, the foundation model works fine. Click
on "ARMv8-A Foundation Model Platform (For Linux Hosts Only)" on the
page linked by Julien. 

You need a cross-compiler, you can download the latest from linaro:

https://releases.linaro.org/components/toolchain/binaries/latest/armv8l-linux-gnueabihf/gcc-linaro-6.3.1-2017.02-x86_64_armv8l-linux-gnueabihf.tar.xz

Then follow these instructions:

http://marc.info/?l=xen-devel=149021352631609

Please read the following emails in the thread too which tells you how
to build Xen and Linux for ARM. We are still solving some issues but the
steps so far are also on the wiki, see "Firmware & boot-wrapper" ->
arm64 and "Foundation Model":

https://wiki.xen.org/wiki/Xen_ARM_with_Virtualization_Extensions/FastModels


> > > Also, what 
> > > version
> > > of git are we supposed to work on ?
> > > 
> > 
> > None of those listed in xen-archives.html.
> > 
> > You need to work on the staging branch of xen.git.
> > 
> > > I would like to work on the XEN-6 task
> > > 
> > > present in JIRA. Can I do it with nested virtualization option ?
> > 
> > I suppose XEN-7 is more suitable.
> > 
> > Unfortunately you can't easily test blktap2 even if you have Xen set up
> > on real hardware. Please be aware that you need to ask for actual
> > blktap2 users to test your change. It's going to take a lot longer to
> > finish.
> 
> You can find a list of small tasks here:
> 
> https://xenproject.atlassian.net/browse/XEN-38?jql=labels%20%3D%20SMALL
> 
> Let us know which one you plan to pick.

XEN-20, XEN-29, XEN-38 are all good candidates. If you have any
questions on the tasks, feel free to ask!


> Cheers,
> 
> [1] https://developer.arm.com/products/system-design/fixed-virtual-platforms


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v10 5/6] x86/ioreq server: Asynchronously reset outstanding p2m_ioreq_server entries.

2017-04-05 Thread Yu Zhang



On 4/6/2017 2:02 AM, Yu Zhang wrote:



On 4/6/2017 1:28 AM, Yu Zhang wrote:



On 4/6/2017 1:18 AM, Yu Zhang wrote:



On 4/6/2017 1:01 AM, George Dunlap wrote:

On 05/04/17 17:32, Yu Zhang wrote:


On 4/6/2017 12:35 AM, George Dunlap wrote:

On 05/04/17 17:22, Yu Zhang wrote:

On 4/5/2017 10:41 PM, George Dunlap wrote:
On Sun, Apr 2, 2017 at 1:24 PM, Yu Zhang 


wrote:
After an ioreq server has unmapped, the remaining 
p2m_ioreq_server

entries need to be reset back to p2m_ram_rw. This patch does this
asynchronously with the current p2m_change_entry_type_global()
interface.

New field entry_count is introduced in struct p2m_domain, to 
record
the number of p2m_ioreq_server p2m page table entries. One 
nature of
these entries is that they only point to 4K sized page frames, 
because
all p2m_ioreq_server entries are originated from p2m_ram_rw 
ones in
p2m_change_type_one(). We do not need to worry about the 
counting for

2M/1G sized pages.

Assuming that all p2m_ioreq_server entries are *created* by
p2m_change_type_one() may valid, but can you assume that they 
are only

ever *removed* by p2m_change_type_one() (or recalculation)?

What happens, for instance, if a guest balloons out one of the ram
pages?  I don't immediately see anything preventing a 
p2m_ioreq_server

page from being ballooned out, nor anything on the
decrease_reservation() path decreasing p2m->ioreq.entry_count.  
Or did

I miss something?

Other than that, only one minor comment...
Thanks for your thorough consideration, George. But I do not 
think we

need to worry about this:

If the emulation is in process, the balloon driver cannot get a
p2m_ioreq_server page - because
it is already allocated.
In theory, yes, the guest *shouldn't* do this.  But what if the 
guest OS

makes a mistake?  Or, what if the ioreq server makes a mistake and
places a watch on a page that *isn't* allocated by the device 
driver, or
forgets to change a page type back to ram when the device driver 
frees

it back to the guest kernel?
Then the lazy p2m change code will be triggered, and this page is 
reset

to p2m_ram_rw
before being set to p2m_invalid, just like the normal path. Will 
this be

a problem?

No, I'm talking about before the ioreq server detaches.

Sorry, I do not get it. Take scenario 1 for example:

Scenario 1: Bug in driver
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server

Here in step 2. the ioreq.entry_count increases;

3. Guest driver accidentally frees A to the kernel
4. guest kernel balloons out page A; ioreq.entry_count is wrong


Here in step 4. the ioreq.entry_count decreases.


Oh. I figured out. This entry is not invalidated yet if ioreq is not 
unmapped. Sorry.



Isn't this what we are expecting?

Yu


Scenario 2: Bug in the kernel
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server
3. Guest kernel tries to balloon out page B, but makes a calculation
mistake and balloons out A instead; now ioreq.entry_count is wrong

Scenario 3: Off-by-one bug in devicemodel
1. Guest driver allocates pages A-D
2. dm makes a mistake and marks pages A-E as p2m_ioreq_server (one 
extra

page)
3. guest kernel balloons out page E; now ioreq.entry_count is wrong

Scenario 4: "Leak" in devicemodel
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server
3. Guest driver is done with page A, but DM forgets to reset it to
p2m_ram_rw
4. Guest driver frees A to guest kernel
5. Guest kernel balloons out page A; now ioreq.entry_count is wrong

I could keep going on; there are *lots* of bugs in the driver, the
kernel, or the devicemodel which could cause pages marked
p2m_ioreq_server to end up being ballooned out; which under the 
current

code would make ioreq.entry_count wrong.

It's the hypervisor's job to do the right thing even when other
components have bugs in them.  This is why I initially suggested 
keeping
count in atomic_write_ept_entry() -- no matter how the entry is 
changed,
we always know exactly how many entries of type p2m_ioreq_server we 
have.




Well, count in atomic_write_ept_entry() only works for ept. Besides, 
it requires

interface changes - need to pass the p2m.
Another thought is - now in XenGT, PoD is disabled to make sure 
gfn->mfn does
not change. So how about we disable ballooning if ioreq.entry_count 
is not 0?


Or maybe just change the p2m_ioreq_server to p2m_ram_rw before it is 
set to p2m_invalid?

Like below code:

diff --git a/xen/common/memory.c b/xen/common/memory.c

index 7dbddda..40e5f63 100644

--- a/xen/common/memory.c

+++ b/xen/common/memory.c

@@ -288,6 +288,10 @@ int guest_remove_page(struct domain *d, unsigned 
long gmfn)


put_gfn(d, gmfn);

return 1;

}

+if ( unlikely(p2mt == p2m_ioreq_server) )

+p2m_change_type_one(d, gmfn,

+p2m_ioreq_server, p2m_ram_rw);

+

#else

mfn = gfn_to_mfn(d, _gfn(gmfn));

#endif



Sorry for the format. Please ignore above code, and see below one:

diff --git a/xen/common/memory.c b/xen/common/memory.c
index 

[Xen-devel] [PATCH] arm64: xen: Implement EFI reset_system callback

2017-04-05 Thread Julien Grall
When rebooting DOM0 with ACPI, the kernel is crashing with the stack trace [1].

This is happening because when EFI runtimes are enabled, the reset code
(see machin_restart) will first try to use EFI restart method.

However, the EFI restart code is expecting the reset_system callback to
be always set. This is not the case for Xen and will lead to crash.

Looking at the reboot path, it is expected to fallback on an alternative
reboot method if one does not work. So implement reset_system callback
as a NOP for Xen.

[   36.999270] reboot: Restarting system
[   37.002921] Internal error: Attempting to execute userspace memory: 8604 
[#1] PREEMPT SMP
[   37.011460] Modules linked in:
[   37.014598] CPU: 0 PID: 1 Comm: systemd-shutdow Not tainted 
4.11.0-rc1-3-g1e248b60a39b-dirty #506
[   37.023903] Hardware name: (null) (DT)
[   37.027734] task: 800902068000 task.stack: 800902064000
[   37.033739] PC is at 0x0
[   37.036359] LR is at efi_reboot+0x94/0xd0
[   37.040438] pc : [<>] lr : [] pstate: 
404001c5
[   37.047920] sp : 800902067cf0
[   37.051314] x29: 800902067cf0 x28: 800902068000
[   37.056709] x27: 08992000 x26: 008e
[   37.062104] x25: 0123 x24: 0015
[   37.067499] x23:  x22: 08e6e250
[   37.072894] x21: 08e6e000 x20: 
[   37.078289] x19: 08e5d4c8 x18: 0010
[   37.083684] x17: a7c27470 x16: deadbeef
[   37.089079] x15: 0006 x14: 88f42bef
[   37.094474] x13: 08f42bfd x12: 08e706c0
[   37.099870] x11: 08e7 x10: 05f5e0ff
[   37.105265] x9 : 800902067a50 x8 : 6974726174736552
[   37.110660] x7 : 08cc6fb8 x6 : 08cc6fb0
[   37.116055] x5 : 08c97dd8 x4 : 
[   37.121453] x3 :  x2 : 
[   37.126845] x1 :  x0 : 
[   37.132239]
[   37.133808] Process systemd-shutdow (pid: 1, stack limit = 
0x800902064000)
[   37.141118] Stack: (0x800902067cf0 to 0x800902068000)
[   37.146949] 7ce0:   800902067d40 
08085334
[   37.154869] 7d00:  08f3b000 800902067d40 
080852e0
[   37.162787] 7d20: 08cc6fb0 08cc6fb8 08c7f580 
08c97dd8
[   37.170706] 7d40: 800902067d60 080e2c2c  
01234567
[   37.178624] 7d60: 800902067d80 080e2ee8  
080e2df4
[   37.186544] 7d80:  080830f0  
8008ff1c1000
[   37.194462] 7da0:  a7c4b1cc  
0024
[   37.202380] 7dc0: 800902067dd0 0005 f24743c8 
0004
[   37.210299] 7de0: f2475f03 0010 f2474418 
0005
[   37.218218] 7e00: f2474578 000a d6b722c0 
0001
[   37.226136] 7e20: 0123 0038 800902067e50 
081e7294
[   37.234055] 7e40: 800902067e60 081e935c 800902067e60 
081e9388
[   37.241973] 7e60: 800902067eb0 081ea388  
8008ff1c1000
[   37.249892] 7e80:  a7c4a79c  
0002
[   37.257810] 7ea0: 0104   
080830f0
[   37.265729] 7ec0: fee1dead 28121969 01234567 

[   37.273651] 7ee0:  80800080 80008080 
feffa9a9d4ff2d66
[   37.281567] 7f00: 008e feffa9a9d5b60e0f 7f7f7f7f 
0101010101010101
[   37.289485] 7f20: 0010 0008 003a 
a7ccf588
[   37.297404] 7f40: d6b87d00 a7c4b1b0 f2474be0 
d6b88000
[   37.305326] 7f60: f2474fb0 01234567  

[   37.313240] 7f80:  0001 d6b70d4d 

[   37.321159] 7fa0: 0001 f2474ea0 d6b5e2e0 
f2474e80
[   37.329078] 7fc0: a7c4b1cc  fee1dead 
008e
[   37.336997] 7fe0:   9ce839cffee77eab 
fafdbf9f7ed57f2f
[   37.344911] Call trace:
[   37.347437] Exception stack(0x800902067b20 to 0x800902067c50)
[   37.353970] 7b20: 08e5d4c8 0001 80f82000 

[   37.361883] 7b40: 800902067b60 08e17000 08f44c68 
0001081081b4
[   37.369802] 7b60: 800902067bf0 08108478  
08c235b0
[   37.377721] 7b80: 800902067ce0   
0015
[   37.385643] 7ba0: 0123 008e 08992000 
800902068000
[   37.393557] 7bc0:   

Re: [Xen-devel] [PATCH v10 5/6] x86/ioreq server: Asynchronously reset outstanding p2m_ioreq_server entries.

2017-04-05 Thread Yu Zhang



On 4/6/2017 1:28 AM, Yu Zhang wrote:



On 4/6/2017 1:18 AM, Yu Zhang wrote:



On 4/6/2017 1:01 AM, George Dunlap wrote:

On 05/04/17 17:32, Yu Zhang wrote:


On 4/6/2017 12:35 AM, George Dunlap wrote:

On 05/04/17 17:22, Yu Zhang wrote:

On 4/5/2017 10:41 PM, George Dunlap wrote:
On Sun, Apr 2, 2017 at 1:24 PM, Yu Zhang 


wrote:

After an ioreq server has unmapped, the remaining p2m_ioreq_server
entries need to be reset back to p2m_ram_rw. This patch does this
asynchronously with the current p2m_change_entry_type_global()
interface.

New field entry_count is introduced in struct p2m_domain, to 
record
the number of p2m_ioreq_server p2m page table entries. One 
nature of
these entries is that they only point to 4K sized page frames, 
because
all p2m_ioreq_server entries are originated from p2m_ram_rw 
ones in
p2m_change_type_one(). We do not need to worry about the 
counting for

2M/1G sized pages.

Assuming that all p2m_ioreq_server entries are *created* by
p2m_change_type_one() may valid, but can you assume that they 
are only

ever *removed* by p2m_change_type_one() (or recalculation)?

What happens, for instance, if a guest balloons out one of the ram
pages?  I don't immediately see anything preventing a 
p2m_ioreq_server

page from being ballooned out, nor anything on the
decrease_reservation() path decreasing p2m->ioreq.entry_count.  
Or did

I miss something?

Other than that, only one minor comment...
Thanks for your thorough consideration, George. But I do not 
think we

need to worry about this:

If the emulation is in process, the balloon driver cannot get a
p2m_ioreq_server page - because
it is already allocated.
In theory, yes, the guest *shouldn't* do this.  But what if the 
guest OS

makes a mistake?  Or, what if the ioreq server makes a mistake and
places a watch on a page that *isn't* allocated by the device 
driver, or
forgets to change a page type back to ram when the device driver 
frees

it back to the guest kernel?
Then the lazy p2m change code will be triggered, and this page is 
reset

to p2m_ram_rw
before being set to p2m_invalid, just like the normal path. Will 
this be

a problem?

No, I'm talking about before the ioreq server detaches.

Sorry, I do not get it. Take scenario 1 for example:

Scenario 1: Bug in driver
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server

Here in step 2. the ioreq.entry_count increases;

3. Guest driver accidentally frees A to the kernel
4. guest kernel balloons out page A; ioreq.entry_count is wrong


Here in step 4. the ioreq.entry_count decreases.


Oh. I figured out. This entry is not invalidated yet if ioreq is not 
unmapped. Sorry.



Isn't this what we are expecting?

Yu


Scenario 2: Bug in the kernel
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server
3. Guest kernel tries to balloon out page B, but makes a calculation
mistake and balloons out A instead; now ioreq.entry_count is wrong

Scenario 3: Off-by-one bug in devicemodel
1. Guest driver allocates pages A-D
2. dm makes a mistake and marks pages A-E as p2m_ioreq_server (one 
extra

page)
3. guest kernel balloons out page E; now ioreq.entry_count is wrong

Scenario 4: "Leak" in devicemodel
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server
3. Guest driver is done with page A, but DM forgets to reset it to
p2m_ram_rw
4. Guest driver frees A to guest kernel
5. Guest kernel balloons out page A; now ioreq.entry_count is wrong

I could keep going on; there are *lots* of bugs in the driver, the
kernel, or the devicemodel which could cause pages marked
p2m_ioreq_server to end up being ballooned out; which under the current
code would make ioreq.entry_count wrong.

It's the hypervisor's job to do the right thing even when other
components have bugs in them.  This is why I initially suggested 
keeping
count in atomic_write_ept_entry() -- no matter how the entry is 
changed,
we always know exactly how many entries of type p2m_ioreq_server we 
have.




Well, count in atomic_write_ept_entry() only works for ept. Besides, 
it requires

interface changes - need to pass the p2m.
Another thought is - now in XenGT, PoD is disabled to make sure 
gfn->mfn does
not change. So how about we disable ballooning if ioreq.entry_count is 
not 0?


Or maybe just change the p2m_ioreq_server to p2m_ram_rw before it is set 
to p2m_invalid?

Like below code:

diff --git a/xen/common/memory.c b/xen/common/memory.c

index 7dbddda..40e5f63 100644

--- a/xen/common/memory.c

+++ b/xen/common/memory.c

@@ -288,6 +288,10 @@ int guest_remove_page(struct domain *d, unsigned 
long gmfn)


put_gfn(d, gmfn);

return 1;

}

+if ( unlikely(p2mt == p2m_ioreq_server) )

+p2m_change_type_one(d, gmfn,

+p2m_ioreq_server, p2m_ram_rw);

+

#else

mfn = gfn_to_mfn(d, _gfn(gmfn));

#endif


Yu



Yu

  -George





___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel




[Xen-devel] [xen-4.5-testing test] 107205: tolerable FAIL - PUSHED

2017-04-05 Thread osstest service owner
flight 107205 xen-4.5-testing real [real]
http://logs.test-lab.xenproject.org/osstest/logs/107205/

Failures :-/ but no regressions.

Tests which are failing intermittently (not blocking):
 test-amd64-amd64-xl-qemuu-debianhvm-amd64 3 host-install(3) broken in 107183 
pass in 107205
 test-amd64-amd64-xl-multivcpu 3 host-install(3) broken in 107183 pass in 107205
 test-amd64-i386-qemut-rhel6hvm-amd 3 host-install(3) broken in 107183 pass in 
107205
 test-amd64-amd64-migrupgrade 3 host-install/src_host(3) broken in 107183 pass 
in 107205
 test-amd64-i386-freebsd10-amd64 3 host-install(3) broken in 107183 pass in 
107205
 test-amd64-amd64-xl-credit2  3 host-install(3) broken in 107183 pass in 107205
 test-amd64-i386-xl-qemuu-debianhvm-amd64 3 host-install(3) broken in 107183 
pass in 107205
 test-amd64-i386-xl-qemuu-ovmf-amd64 9 debian-hvm-install fail in 107183 pass 
in 107205
 test-amd64-i386-qemuu-rhel6hvm-intel 11 guest-start/redhat.repeat fail in 
107183 pass in 107205
 test-amd64-amd64-libvirt-vhd 13 guest-saverestore  fail pass in 107183

Regressions which are regarded as allowable (not blocking):
 test-armhf-armhf-xl-rtds 11 guest-start fail in 107183 like 106840
 test-armhf-armhf-xl-rtds 15 guest-start/debian.repeatfail  like 106818
 test-amd64-i386-xl-qemuu-win7-amd64 15 guest-localmigrate/x10 fail like 106840
 test-amd64-amd64-xl-rtds  6 xen-boot fail  like 106872
 test-xtf-amd64-amd64-2   54 leak-check/check fail  like 106872
 test-xtf-amd64-amd64-3   54 leak-check/check fail  like 106872
 test-xtf-amd64-amd64-4   54 leak-check/check fail  like 106872
 test-xtf-amd64-amd64-1   54 leak-check/check fail  like 106872
 test-xtf-amd64-amd64-5   54 leak-check/check fail  like 106872
 test-armhf-armhf-libvirt 13 saverestore-support-checkfail  like 106872
 test-amd64-amd64-xl-qemut-win7-amd64 16 guest-stopfail like 106872
 test-amd64-amd64-xl-qemuu-win7-amd64 16 guest-stopfail like 106872
 test-amd64-i386-xl-qemut-win7-amd64 16 guest-stop fail like 106872

Tests which did not succeed, but are not blocking:
 test-xtf-amd64-amd64-2   18 xtf/test-hvm32-cpuid-faulting fail  never pass
 test-xtf-amd64-amd64-2 31 xtf/test-hvm32pae-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-2 37 xtf/test-hvm32pse-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-2   41 xtf/test-hvm64-cpuid-faulting fail  never pass
 test-xtf-amd64-amd64-4   18 xtf/test-hvm32-cpuid-faulting fail  never pass
 test-xtf-amd64-amd64-1   18 xtf/test-hvm32-cpuid-faulting fail  never pass
 test-xtf-amd64-amd64-4 31 xtf/test-hvm32pae-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-4 37 xtf/test-hvm32pse-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-1 31 xtf/test-hvm32pae-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-4   41 xtf/test-hvm64-cpuid-faulting fail  never pass
 test-xtf-amd64-amd64-1 37 xtf/test-hvm32pse-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-1   41 xtf/test-hvm64-cpuid-faulting fail  never pass
 test-xtf-amd64-amd64-5   18 xtf/test-hvm32-cpuid-faulting fail  never pass
 test-amd64-amd64-xl-pvh-intel 11 guest-start  fail  never pass
 test-xtf-amd64-amd64-5 31 xtf/test-hvm32pae-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-5 37 xtf/test-hvm32pse-cpuid-faulting fail never pass
 test-xtf-amd64-amd64-5   41 xtf/test-hvm64-cpuid-faulting fail  never pass
 test-amd64-amd64-libvirt 12 migrate-support-checkfail   never pass
 test-amd64-amd64-xl-pvh-amd  11 guest-start  fail   never pass
 test-amd64-i386-libvirt  12 migrate-support-checkfail   never pass
 test-xtf-amd64-amd64-2   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-xtf-amd64-amd64-3   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-xtf-amd64-amd64-4   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-xtf-amd64-amd64-1   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-xtf-amd64-amd64-5   53 xtf/test-hvm64-xsa-195   fail   never pass
 test-armhf-armhf-xl-arndale  12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-arndale  13 saverestore-support-checkfail   never pass
 test-amd64-amd64-libvirt-vhd 11 migrate-support-checkfail   never pass
 test-amd64-amd64-qemuu-nested-amd 16 debian-hvm-install/l1/l2  fail never pass
 test-armhf-armhf-xl-cubietruck 12 migrate-support-checkfail never pass
 test-armhf-armhf-xl-cubietruck 13 saverestore-support-checkfail never pass
 test-armhf-armhf-xl-multivcpu 12 migrate-support-checkfail  never pass
 test-armhf-armhf-xl-multivcpu 13 saverestore-support-checkfail  never pass
 test-armhf-armhf-libvirt 12 migrate-support-checkfail   never pass
 test-armhf-armhf-xl-vhd  10 guest-start 

[Xen-devel] [PATCH v2 for-4.9 0/7] x86/emul: Userspace fuzzing harness fixes

2017-04-05 Thread Andrew Cooper
This is a subset of the previous fuzzing bugfix/improvement series, which is
the minimum required to avoid hitting assertions in the emulator.

From a 4.9 point of view, this entirely userspace testing harness changes (so
safe to take), but it allows us to sensibly fuzz the emulator in the
hypervisor (rather than hitting a load of assertions).

Andrew Cooper (7):
  MAINTAINERS: Move the x86 instruction emulator under x86 maintainership
  tools/insn-fuzz: Don't hit memcpy() for zero-length reads
  tools/insn-fuzz: Avoid making use of static data
  tools/insn-fuzz: Fix a stability bug in afl-clang-fast mode
  tools/insn-fuzz: Correct hook prototypes, and assert() appropriate segments
  tools/insn-fuzz: Provide IA32_DEBUGCTL consistently to the emulator
  tools/insn-fuzz: Fix assertion failures in x86_emulate_wrapper()

 MAINTAINERS |   1 +
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 268 +---
 tools/tests/x86_emulator/test_x86_emulator.c|   8 +-
 3 files changed, 196 insertions(+), 81 deletions(-)

-- 
2.1.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 for-4.9 5/7] tools/insn-fuzz: Correct hook prototypes, and assert() appropriate segments

2017-04-05 Thread Andrew Cooper
The correct prototypes for the hooks are to use enum x86_segment rather than
unsigned int.  It is implementation specific as to whether this compiles.

assert() that the emulator never passes an inappropriate segment.  The only
hook which may legitimately be passed x86_seg_none is invlpg().

Signed-off-by: Andrew Cooper 
---
CC: Jan Beulich 
CC: George Dunlap 
CC: Ian Jackson 
CC: Wei Liu 
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 45 -
 tools/tests/x86_emulator/test_x86_emulator.c|  8 ++---
 2 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index a20212e..fedeb9f 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -117,12 +117,15 @@ static int data_read(struct x86_emulate_ctxt *ctxt,
 }
 
 static int fuzz_read(
-unsigned int seg,
+enum x86_segment seg,
 unsigned long offset,
 void *p_data,
 unsigned int bytes,
 struct x86_emulate_ctxt *ctxt)
 {
+/* Reads expected for all user and system segments. */
+assert((unsigned int)seg < x86_seg_none);
+
 return data_read(ctxt, "read", p_data, bytes);
 }
 
@@ -136,12 +139,14 @@ static int fuzz_read_io(
 }
 
 static int fuzz_insn_fetch(
-unsigned int seg,
+enum x86_segment seg,
 unsigned long offset,
 void *p_data,
 unsigned int bytes,
 struct x86_emulate_ctxt *ctxt)
 {
+assert(seg == x86_seg_cs);
+
 /*
  * Zero-length instruction fetches are made at the destination of jumps,
  * to perform segmentation checks.  No data needs returning.
@@ -211,6 +216,8 @@ static int fuzz_rep_ins(
 unsigned long *reps,
 struct x86_emulate_ctxt *ctxt)
 {
+assert(dst_seg == x86_seg_es);
+
 return _fuzz_rep_read(ctxt, "rep_ins", reps);
 }
 
@@ -223,6 +230,9 @@ static int fuzz_rep_movs(
 unsigned long *reps,
 struct x86_emulate_ctxt *ctxt)
 {
+assert(is_x86_user_segment(src_seg));
+assert(dst_seg == x86_seg_es);
+
 return _fuzz_rep_read(ctxt, "rep_movs", reps);
 }
 
@@ -234,6 +244,8 @@ static int fuzz_rep_outs(
 unsigned long *reps,
 struct x86_emulate_ctxt *ctxt)
 {
+assert(is_x86_user_segment(src_seg));
+
 return _fuzz_rep_write(ctxt, "rep_outs", reps);
 }
 
@@ -245,27 +257,43 @@ static int fuzz_rep_stos(
 unsigned long *reps,
 struct x86_emulate_ctxt *ctxt)
 {
+/*
+ * STOS itself may only have an %es segment, but the stos() hook is reused
+ * for CLZERO.
+ */
+assert(is_x86_user_segment(seg));
+
 return _fuzz_rep_write(ctxt, "rep_stos", reps);
 }
 
 static int fuzz_write(
-unsigned int seg,
+enum x86_segment seg,
 unsigned long offset,
 void *p_data,
 unsigned int bytes,
 struct x86_emulate_ctxt *ctxt)
 {
+/* Writes not expected for any system segments. */
+assert(is_x86_user_segment(seg));
+
 return maybe_fail(ctxt, "write", true);
 }
 
 static int fuzz_cmpxchg(
-unsigned int seg,
+enum x86_segment seg,
 unsigned long offset,
 void *old,
 void *new,
 unsigned int bytes,
 struct x86_emulate_ctxt *ctxt)
 {
+/*
+ * Cmpxchg expected for user segments, and setting accessed/busy bits in
+ * GDT/LDT enties, but not expected for any IDT or TR accesses.
+ */
+assert(is_x86_user_segment(seg) ||
+   seg == x86_seg_gdtr || seg == x86_seg_ldtr);
+
 return maybe_fail(ctxt, "cmpxchg", true);
 }
 
@@ -274,6 +302,9 @@ static int fuzz_invlpg(
 unsigned long offset,
 struct x86_emulate_ctxt *ctxt)
 {
+/* invlpg(), unlike all other hooks, may be called with x86_seg_none. */
+assert((unsigned int)seg <= x86_seg_none);
+
 return maybe_fail(ctxt, "invlpg", false);
 }
 
@@ -300,8 +331,7 @@ static int fuzz_read_segment(
 const struct fuzz_state *s = ctxt->data;
 const struct fuzz_corpus *c = s->corpus;
 
-if ( seg >= SEG_NUM )
-return X86EMUL_UNHANDLEABLE;
+assert((unsigned int)seg < x86_seg_none);
 
 *reg = c->segments[seg];
 
@@ -317,8 +347,7 @@ static int fuzz_write_segment(
 struct fuzz_corpus *c = s->corpus;
 int rc;
 
-if ( seg >= SEG_NUM )
-return X86EMUL_UNHANDLEABLE;
+assert((unsigned int)seg < x86_seg_none);
 
 rc = maybe_fail(ctxt, "write_segment", true);
 
diff --git a/tools/tests/x86_emulator/test_x86_emulator.c 
b/tools/tests/x86_emulator/test_x86_emulator.c
index efeb175..1992c3f 100644
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -155,7 +155,7 @@ static const struct {
 static unsigned int bytes_read;
 
 static int read(
-unsigned int seg,
+enum x86_segment seg,
 unsigned long offset,
 void *p_data,
 unsigned int bytes,
@@ -210,7 +210,7 @@ static int 

[Xen-devel] [PATCH v2 for-4.9 7/7] tools/insn-fuzz: Fix assertion failures in x86_emulate_wrapper()

2017-04-05 Thread Andrew Cooper
c/s 92cf67888 "x86/emul: Hold x86_emulate() to strict X86EMUL_EXCEPTION
requirements" was appropriate for the hypervisor, but the fuzzer stubs didn't
conform to the stricter requirements.  AFL is very quick to discover this.

Extend the fuzzing harness exception logic to raise exceptions appropriately.

Signed-off-by: Andrew Cooper 
Reviewed-by: Jan Beulich 
---
CC: George Dunlap 
CC: Ian Jackson 
CC: Wei Liu 
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 27 -
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index 9e3a10a..8cf683d 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -86,10 +86,15 @@ static int maybe_fail(struct x86_emulate_ctxt *ctxt,
 
 printf("maybe_fail %s: %d\n", why, rc);
 
+if ( rc == X86EMUL_EXCEPTION )
+/* Fake up a pagefault. */
+x86_emul_pagefault(0, 0, ctxt);
+
 return rc;
 }
 
 static int data_read(struct x86_emulate_ctxt *ctxt,
+ enum x86_segment seg,
  const char *why, void *dst, unsigned int bytes)
 {
 struct fuzz_state *s = ctxt->data;
@@ -98,7 +103,17 @@ static int data_read(struct x86_emulate_ctxt *ctxt,
 int rc;
 
 if ( s->data_index + bytes > s->data_num )
+{
+/*
+ * Fake up a segment limit violation.  System segment limit volations
+ * are reported by X86EMUL_EXCEPTION alone, so the emulator can fill
+ * in the correct context.
+ */
+if ( !is_x86_system_segment(seg) )
+x86_emul_hw_exception(13, 0, ctxt);
+
 rc = X86EMUL_EXCEPTION;
+}
 else
 rc = maybe_fail(ctxt, why, true);
 
@@ -126,7 +141,7 @@ static int fuzz_read(
 /* Reads expected for all user and system segments. */
 assert((unsigned int)seg < x86_seg_none);
 
-return data_read(ctxt, "read", p_data, bytes);
+return data_read(ctxt, seg, "read", p_data, bytes);
 }
 
 static int fuzz_read_io(
@@ -135,7 +150,7 @@ static int fuzz_read_io(
 unsigned long *val,
 struct x86_emulate_ctxt *ctxt)
 {
-return data_read(ctxt, "read_io", val, bytes);
+return data_read(ctxt, x86_seg_none, "read_io", val, bytes);
 }
 
 static int fuzz_insn_fetch(
@@ -157,7 +172,7 @@ static int fuzz_insn_fetch(
 return maybe_fail(ctxt, "insn_fetch", true);
 }
 
-return data_read(ctxt, "insn_fetch", p_data, bytes);
+return data_read(ctxt, seg, "insn_fetch", p_data, bytes);
 }
 
 static int _fuzz_rep_read(struct x86_emulate_ctxt *ctxt,
@@ -166,7 +181,7 @@ static int _fuzz_rep_read(struct x86_emulate_ctxt *ctxt,
 int rc;
 unsigned long bytes_read = 0;
 
-rc = data_read(ctxt, why, _read, sizeof(bytes_read));
+rc = data_read(ctxt, x86_seg_none, why, _read, sizeof(bytes_read));
 
 if ( bytes_read <= *reps )
 *reps = bytes_read;
@@ -436,7 +451,7 @@ static int fuzz_read_msr(
  * should preferably return consistent values, but returning
  * random values is fine in fuzzer.
  */
-return data_read(ctxt, "read_msr", val, sizeof(*val));
+return data_read(ctxt, x86_seg_none, "read_msr", val, sizeof(*val));
 case MSR_EFER:
 *val = c->msr[MSRI_EFER];
 *val &= ~EFER_LMA;
@@ -458,6 +473,7 @@ static int fuzz_read_msr(
 }
 }
 
+x86_emul_hw_exception(13, 0, ctxt);
 return X86EMUL_EXCEPTION;
 }
 
@@ -491,6 +507,7 @@ static int fuzz_write_msr(
 }
 }
 
+x86_emul_hw_exception(13, 0, ctxt);
 return X86EMUL_EXCEPTION;
 }
 
-- 
2.1.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 for-4.9 1/7] MAINTAINERS: Move the x86 instruction emulator under x86 maintainership

2017-04-05 Thread Andrew Cooper
Requested-by: Jan Beulich 
Signed-off-by: Andrew Cooper 
--
CC: George Dunlap 
CC: Ian Jackson 
CC: Jan Beulich 
CC: Konrad Rzeszutek Wilk 
CC: Stefano Stabellini 
CC: Tim Deegan 
CC: Wei Liu 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index c38bcd4..bee9d49 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -434,6 +434,7 @@ F:  xen/arch/x86/
 F: xen/include/asm-x86/
 F: tools/firmware/hvmloader/
 F: tools/tests/x86_emulator/
+F: tools/fuzz/x86_instruction_emulator/
 
 X86 I/O EMULATION
 M: Paul Durrant 
-- 
2.1.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 for-4.9 6/7] tools/insn-fuzz: Provide IA32_DEBUGCTL consistently to the emulator

2017-04-05 Thread Andrew Cooper
x86_emulates()'s is_branch_step() performs a speculative read of
IA32_DEBUGCTL, but doesn't squash exceptions should they arise.  In reality,
this MSR is always available.

Signed-off-by: Andrew Cooper 
Reviewed-by: Jan Beulich 
---
CC: George Dunlap 
CC: Ian Jackson 
CC: Wei Liu 
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index fedeb9f..9e3a10a 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -402,7 +402,8 @@ enum {
 MSRI_STAR,
 MSRI_LSTAR,
 MSRI_CSTAR,
-MSRI_SYSCALL_MASK
+MSRI_SYSCALL_MASK,
+MSRI_IA32_DEBUGCTLMSR,
 };
 
 static const unsigned int msr_index[MSR_INDEX_MAX] = {
@@ -413,7 +414,8 @@ static const unsigned int msr_index[MSR_INDEX_MAX] = {
 [MSRI_STAR]  = MSR_STAR,
 [MSRI_LSTAR] = MSR_LSTAR,
 [MSRI_CSTAR] = MSR_CSTAR,
-[MSRI_SYSCALL_MASK]  = MSR_SYSCALL_MASK
+[MSRI_SYSCALL_MASK]  = MSR_SYSCALL_MASK,
+[MSRI_IA32_DEBUGCTLMSR]  = MSR_IA32_DEBUGCTLMSR,
 };
 
 static int fuzz_read_msr(
-- 
2.1.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 for-4.9 3/7] tools/insn-fuzz: Avoid making use of static data

2017-04-05 Thread Andrew Cooper
AFL has a measure of stability, where it passes the same corpus into the
fuzzing harness and observes whether the execution path changes from before.
Any instability in the fuzzing harness reduces its effectiveness, as an
observed crash may not reliably be caused by the original corpus.

In preparation to fix a stability bug, introduce struct fuzz_state, allocated
on the stack and passed around via struct x86_emulate_ctxt's data parameter.
Propagate ctxt into the helpers such as maybe_fail(), so the state can be
retrieved.

Move the previously-static data_{index,num} into struct fuzz_state.

Signed-off-by: Andrew Cooper 
Reviewed-by: Jan Beulich 
---
CC: George Dunlap 
CC: Ian Jackson 
CC: Wei Liu 
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 181 +++-
 1 file changed, 116 insertions(+), 65 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index 64b7fb2..db0719e 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -21,7 +21,9 @@
 
 #define SEG_NUM x86_seg_none
 
-struct input_struct {
+/* Layout of data expected as fuzzing input. */
+struct fuzz_corpus
+{
 unsigned long cr[5];
 uint64_t msr[MSR_INDEX_MAX];
 struct cpu_user_regs regs;
@@ -29,19 +31,36 @@ struct input_struct {
 unsigned long options;
 unsigned char data[4096];
 } input;
-#define DATA_OFFSET offsetof(struct input_struct, data)
-static unsigned int data_index;
-static unsigned int data_num;
+#define DATA_OFFSET offsetof(struct fuzz_corpus, data)
+
+/*
+ * Internal state of the fuzzing harness.  Calculated initially from the input
+ * corpus, and later mutates by the emulation callbacks.
+ */
+struct fuzz_state
+{
+/* Fuzzer's input data. */
+struct fuzz_corpus *corpus;
+
+/* Real amount of data backing corpus->data[]. */
+size_t data_num;
+
+/* Amount of corpus->data[] consumed thus far. */
+size_t data_index;
+};
 
 /*
  * Randomly return success or failure when processing data.  If
  * `exception` is false, this function turns _EXCEPTION to _OKAY.
  */
-static int maybe_fail(const char *why, bool exception)
+static int maybe_fail(struct x86_emulate_ctxt *ctxt,
+  const char *why, bool exception)
 {
+struct fuzz_state *s = ctxt->data;
+const struct fuzz_corpus *c = s->corpus;
 int rc;
 
-if ( data_index >= data_num )
+if ( s->data_index >= s->data_num )
 rc = X86EMUL_EXCEPTION;
 else
 {
@@ -50,13 +69,13 @@ static int maybe_fail(const char *why, bool exception)
  * 25% unhandlable
  * 25% exception
  */
-if ( input.data[data_index] > 0xc0 )
+if ( c->data[s->data_index] > 0xc0 )
 rc = X86EMUL_EXCEPTION;
-else if ( input.data[data_index] > 0x80 )
+else if ( c->data[s->data_index] > 0x80 )
 rc = X86EMUL_UNHANDLEABLE;
 else
 rc = X86EMUL_OKAY;
-data_index++;
+s->data_index++;
 }
 
 if ( rc == X86EMUL_EXCEPTION && !exception )
@@ -67,20 +86,23 @@ static int maybe_fail(const char *why, bool exception)
 return rc;
 }
 
-static int data_read(const char *why, void *dst, unsigned int bytes)
+static int data_read(struct x86_emulate_ctxt *ctxt,
+ const char *why, void *dst, unsigned int bytes)
 {
+struct fuzz_state *s = ctxt->data;
+const struct fuzz_corpus *c = s->corpus;
 unsigned int i;
 int rc;
 
-if ( data_index + bytes > data_num )
+if ( s->data_index + bytes > s->data_num )
 rc = X86EMUL_EXCEPTION;
 else
-rc = maybe_fail(why, true);
+rc = maybe_fail(ctxt, why, true);
 
 if ( rc == X86EMUL_OKAY )
 {
-memcpy(dst,  input.data + data_index, bytes);
-data_index += bytes;
+memcpy(dst, >data[s->data_index], bytes);
+s->data_index += bytes;
 
 printf("%s: ", why);
 for ( i = 0; i < bytes; i++ )
@@ -98,7 +120,7 @@ static int fuzz_read(
 unsigned int bytes,
 struct x86_emulate_ctxt *ctxt)
 {
-return data_read("read", p_data, bytes);
+return data_read(ctxt, "read", p_data, bytes);
 }
 
 static int fuzz_read_io(
@@ -107,7 +129,7 @@ static int fuzz_read_io(
 unsigned long *val,
 struct x86_emulate_ctxt *ctxt)
 {
-return data_read("read_io", val, bytes);
+return data_read(ctxt, "read_io", val, bytes);
 }
 
 static int fuzz_insn_fetch(
@@ -124,18 +146,19 @@ static int fuzz_insn_fetch(
 if ( bytes == 0 )
 {
 assert(p_data == NULL);
-return maybe_fail("insn_fetch", true);
+return maybe_fail(ctxt, "insn_fetch", true);
 }
 
-return data_read("insn_fetch", p_data, bytes);
+return data_read(ctxt, "insn_fetch", p_data, bytes);
 }
 
-static int 

[Xen-devel] [PATCH v2 for-4.9 4/7] tools/insn-fuzz: Fix a stability bug in afl-clang-fast mode

2017-04-05 Thread Andrew Cooper
The fuzzing harness conditionally disables hooks to test error paths in the
emulator.  However, fuzz_emulops is a static structure.

c/s 69f4633 "tools/insn-fuzz: Support AFL's afl-clang-fast mode" introduced
persistent mode, but because fuzz_emulops is static, the clobbering of hooks
accumulates over repeated input, meaning that previous corpora influence the
execution over the current corpus.

Move the partially clobbered struct x86_emulate_ops into struct fuzz_state,
which is re-initialised from full on each call to LLVMFuzzerTestOneInput()

Signed-off-by: Andrew Cooper 
Reviewed-by: Jan Beulich 
---
CC: George Dunlap 
CC: Ian Jackson 
CC: Wei Liu 
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index db0719e..a20212e 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -47,6 +47,9 @@ struct fuzz_state
 
 /* Amount of corpus->data[] consumed thus far. */
 size_t data_index;
+
+/* Emulation ops, some of which are disabled based on corpus->options. */
+struct x86_emulate_ops ops;
 };
 
 /*
@@ -461,7 +464,7 @@ static int fuzz_write_msr(
 }
 
 #define SET(h) .h = fuzz_##h
-static struct x86_emulate_ops fuzz_emulops = {
+static const struct x86_emulate_ops all_fuzzer_ops = {
 SET(read),
 SET(insn_fetch),
 SET(write),
@@ -603,7 +606,7 @@ enum {
 #define MAYBE_DISABLE_HOOK(h)  \
 if ( bitmap & (1 << HOOK_##h) )\
 {  \
-fuzz_emulops.h = NULL; \
+s->ops.h = NULL;   \
 printf("Disabling hook "#h"\n");   \
 }
 
@@ -709,7 +712,9 @@ int LLVMFuzzerInitialize(int *argc, char ***argv)
 int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size)
 {
 struct cpu_user_regs regs = {};
-struct fuzz_state state = {};
+struct fuzz_state state = {
+.ops = all_fuzzer_ops,
+};
 struct x86_emulate_ctxt ctxt = {
 .data = ,
 .regs = ,
@@ -749,7 +754,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t 
size)
 set_sizes();
 dump_state();
 
-rc = x86_emulate(, _emulops);
+rc = x86_emulate(, );
 printf("Emulation result: %d\n", rc);
 } while ( rc == X86EMUL_OKAY );
 
-- 
2.1.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 for-4.9 2/7] tools/insn-fuzz: Don't hit memcpy() for zero-length reads

2017-04-05 Thread Andrew Cooper
For control-flow changes, the emulator needs to perform a zero-length
instruction fetch at the target offset.  It also passes NULL for the
destination buffer, as there is no instruction stream to collect.

This trips up UBSAN when passed to memcpy(), as passing NULL is undefined
behaviour per the C spec (irrespective of passing a size of 0).

Special case these fetches in fuzz_insn_fetch() before reaching data_read().

Signed-off-by: Andrew Cooper 
Acked-by: George Dunlap 
---
CC: Jan Beulich 
CC: Ian Jackson 
CC: Wei Liu 

v2:
 * Rework in terms of special casing zero-length fetches only.
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index 65c5a3b..64b7fb2 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -117,6 +117,16 @@ static int fuzz_insn_fetch(
 unsigned int bytes,
 struct x86_emulate_ctxt *ctxt)
 {
+/*
+ * Zero-length instruction fetches are made at the destination of jumps,
+ * to perform segmentation checks.  No data needs returning.
+ */
+if ( bytes == 0 )
+{
+assert(p_data == NULL);
+return maybe_fail("insn_fetch", true);
+}
+
 return data_read("insn_fetch", p_data, bytes);
 }
 
-- 
2.1.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH v6] altp2m: Introduce external-only and limited use-cases

2017-04-05 Thread Tamas K Lengyel
On Wed, Apr 5, 2017 at 9:04 AM, George Dunlap  wrote:
> On Tue, Apr 4, 2017 at 4:24 PM, Tamas K Lengyel
>  wrote:
>> Currently setting altp2mhvm=1 in the domain configuration allows access to 
>> the
>> altp2m interface for both in-guest and external privileged tools. This poses
>> a problem for use-cases where only external access should be allowed, 
>> requiring
>> the user to compile Xen with XSM enabled to be able to appropriately restrict
>> access.
>>
>> In this patch we deprecate the altp2mhvm domain configuration option and
>> introduce the altp2m option, which allows specifying if by default the altp2m
>> interface should be external-only or limited. The information is stored in
>> HVM_PARAM_ALTP2M which we now define with specific XEN_ALTP2M_* modes.
>> If external mode is selected, the XSM check is shifted to use XSM_DM_PRIV
>> type check, thus restricting access to the interface by the guest itself. 
>> Note
>> that we keep the default XSM policy untouched. Users of XSM who wish to 
>> enforce
>> external mode for altp2m can do so by adjusting their XSM policy directly,
>> as this domain config option does not override an active XSM policy.
>>
>> Also, as part of this patch we adjust the hvmop handler to require
>> HVM_PARAM_ALTP2M to be of a type other then disabled for all ops. This has 
>> been
>> previously only required for get/set altp2m domain state, all other options
>> were gated on altp2m_enabled. Since altp2m_enabled only gets set during set
>> altp2m domain state, this change introduces no new requirements to the other
>> ops but makes it more clear that it is required for all ops.
>>
>> Signed-off-by: Tamas K Lengyel 
>> Signed-off-by: Sergej Proskurin 
>> Acked-by: Wei Liu 
>> ---
>> Cc: Ian Jackson 
>> Cc: Andrew Cooper 
>> Cc: Jan Beulich 
>> Cc: Daniel De Graaf 
>>
>> v5: Add "limited" mode where the guest only has access to enable/disable
>> VMFUNC and #VE features.
>>
>> v6: Check mode when XSM is enabled so that both the mode and the XSM policy
>> has to allow the altp2m operation to succeed. Makes limited mode 
>> available
>> even when XSM is enabled.
>> ---
>>  docs/man/xl.cfg.pod.5.in| 41 
>> -
>>  tools/libxl/libxl_create.c  |  6 --
>>  tools/libxl/libxl_dom.c | 18 --
>>  tools/libxl/libxl_types.idl | 14 ++
>>  tools/xl/xl_parse.c | 20 +++-
>>  xen/arch/x86/hvm/hvm.c  | 22 --
>>  xen/include/public/hvm/params.h | 12 +++-
>>  xen/include/xsm/dummy.h | 23 ---
>>  xen/include/xsm/xsm.h   |  6 +++---
>>  xen/xsm/flask/hooks.c   | 21 -
>>  10 files changed, 159 insertions(+), 24 deletions(-)
>>
>> diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in
>> index 206d33eb3f..616dc093b0 100644
>> --- a/docs/man/xl.cfg.pod.5.in
>> +++ b/docs/man/xl.cfg.pod.5.in
>> @@ -1319,6 +1319,41 @@ enabled by default and you should usually omit it. It 
>> may be necessary
>>  to disable the HPET in order to improve compatibility with guest
>>  Operating Systems (X86 only)
>>
>> +=item 

Re: [Xen-devel] [PATCH v10 5/6] x86/ioreq server: Asynchronously reset outstanding p2m_ioreq_server entries.

2017-04-05 Thread Yu Zhang



On 4/6/2017 1:18 AM, Yu Zhang wrote:



On 4/6/2017 1:01 AM, George Dunlap wrote:

On 05/04/17 17:32, Yu Zhang wrote:


On 4/6/2017 12:35 AM, George Dunlap wrote:

On 05/04/17 17:22, Yu Zhang wrote:

On 4/5/2017 10:41 PM, George Dunlap wrote:
On Sun, Apr 2, 2017 at 1:24 PM, Yu Zhang 


wrote:

After an ioreq server has unmapped, the remaining p2m_ioreq_server
entries need to be reset back to p2m_ram_rw. This patch does this
asynchronously with the current p2m_change_entry_type_global()
interface.

New field entry_count is introduced in struct p2m_domain, to record
the number of p2m_ioreq_server p2m page table entries. One 
nature of
these entries is that they only point to 4K sized page frames, 
because

all p2m_ioreq_server entries are originated from p2m_ram_rw ones in
p2m_change_type_one(). We do not need to worry about the 
counting for

2M/1G sized pages.

Assuming that all p2m_ioreq_server entries are *created* by
p2m_change_type_one() may valid, but can you assume that they are 
only

ever *removed* by p2m_change_type_one() (or recalculation)?

What happens, for instance, if a guest balloons out one of the ram
pages?  I don't immediately see anything preventing a 
p2m_ioreq_server

page from being ballooned out, nor anything on the
decrease_reservation() path decreasing p2m->ioreq.entry_count.  
Or did

I miss something?

Other than that, only one minor comment...

Thanks for your thorough consideration, George. But I do not think we
need to worry about this:

If the emulation is in process, the balloon driver cannot get a
p2m_ioreq_server page - because
it is already allocated.
In theory, yes, the guest *shouldn't* do this.  But what if the 
guest OS

makes a mistake?  Or, what if the ioreq server makes a mistake and
places a watch on a page that *isn't* allocated by the device 
driver, or

forgets to change a page type back to ram when the device driver frees
it back to the guest kernel?

Then the lazy p2m change code will be triggered, and this page is reset
to p2m_ram_rw
before being set to p2m_invalid, just like the normal path. Will 
this be

a problem?

No, I'm talking about before the ioreq server detaches.

Sorry, I do not get it. Take scenario 1 for example:

Scenario 1: Bug in driver
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server

Here in step 2. the ioreq.entry_count increases;

3. Guest driver accidentally frees A to the kernel
4. guest kernel balloons out page A; ioreq.entry_count is wrong


Here in step 4. the ioreq.entry_count decreases.


Oh. I figured out. This entry is not invalidated yet if ioreq is not 
unmapped. Sorry.



Isn't this what we are expecting?

Yu


Scenario 2: Bug in the kernel
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server
3. Guest kernel tries to balloon out page B, but makes a calculation
mistake and balloons out A instead; now ioreq.entry_count is wrong

Scenario 3: Off-by-one bug in devicemodel
1. Guest driver allocates pages A-D
2. dm makes a mistake and marks pages A-E as p2m_ioreq_server (one extra
page)
3. guest kernel balloons out page E; now ioreq.entry_count is wrong

Scenario 4: "Leak" in devicemodel
1. Guest driver allocates page A
2. dm marks A as p2m_ioreq_server
3. Guest driver is done with page A, but DM forgets to reset it to
p2m_ram_rw
4. Guest driver frees A to guest kernel
5. Guest kernel balloons out page A; now ioreq.entry_count is wrong

I could keep going on; there are *lots* of bugs in the driver, the
kernel, or the devicemodel which could cause pages marked
p2m_ioreq_server to end up being ballooned out; which under the current
code would make ioreq.entry_count wrong.

It's the hypervisor's job to do the right thing even when other
components have bugs in them.  This is why I initially suggested keeping
count in atomic_write_ept_entry() -- no matter how the entry is changed,
we always know exactly how many entries of type p2m_ioreq_server we 
have.




Well, count in atomic_write_ept_entry() only works for ept. Besides, it 
requires

interface changes - need to pass the p2m.
Another thought is - now in XenGT, PoD is disabled to make sure gfn->mfn 
does
not change. So how about we disable ballooning if ioreq.entry_count is 
not 0?


Yu

  -George





___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel



___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 for-4.9 0/6] x86/emul: Fixes

2017-04-05 Thread Andrew Cooper
This series started out as patches 4 and 5, to aid the userspace fuzzing
harness, but ended up discovering the bug in patch 3, which is security
relevant.

Patch 3 is a must-fix for Xen 4.9, before the bug needs an XSA.  Patches 4-6
are nice-to-have.

The main change from v1 is reworking of patch 3.

Andrew Cooper (6):
  x86/hvm: Correct some address space terminology
  x86/hvm: Correct long mode predicate
  x86/hvm: Fix segmentation logic for system segments
  x86/svm: Introduce svm_emul_swint_injection()
  x86/emul: Drop swint_emulate infrastructure
  x86/emul: Require callers to provide LMA in the emulation context

 tools/fuzz/x86_instruction_emulator/fuzz-emul.c |  20 +-
 tools/tests/x86_emulator/test_x86_emulator.c|   4 +
 xen/arch/x86/cpuid.c|   2 +-
 xen/arch/x86/hvm/emulate.c  |  25 +--
 xen/arch/x86/hvm/hvm.c  |  77 
 xen/arch/x86/hvm/svm/svm.c  | 139 +-
 xen/arch/x86/hvm/vmx/vmx.c  |   6 +-
 xen/arch/x86/hvm/vmx/vvmx.c |   8 +-
 xen/arch/x86/mm.c   |   4 +-
 xen/arch/x86/mm/hap/hap.c   |   8 +-
 xen/arch/x86/mm/shadow/common.c |  25 ++-
 xen/arch/x86/oprofile/backtrace.c   |   2 +-
 xen/arch/x86/traps.c|   1 +
 xen/arch/x86/x86_emulate/x86_emulate.c  | 238 
 xen/arch/x86/x86_emulate/x86_emulate.h  |  56 +-
 xen/include/asm-x86/hvm/hvm.h   |   5 +-
 16 files changed, 266 insertions(+), 354 deletions(-)

-- 
2.1.4


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH v2 for-4.9 6/6] x86/emul: Require callers to provide LMA in the emulation context

2017-04-05 Thread Andrew Cooper
Long mode (or not) influences emulation behaviour in a number of cases.
Instead of reusing the ->read_msr() hook to obtain EFER.LMA, require callers
to provide it directly.

This simplifies all long mode checks during emulation to a simple boolean
read, removing embedded msr reads.  It also allows for the removal of a local
variable in the sysenter emulation block, and removes a latent bug in the
syscall emulation block where rc contains a non X86EMUL_* constant for a
period of time.

Signed-off-by: Andrew Cooper 
Reviewed-by: Paul Durrant 
---
CC: Jan Beulich 
CC: Tim Deegan 
CC: Julien Grall 

v2:
 * Move lma to the in/out section of x86_emulate_ctxt
 * Replace one 0 with false
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c |  2 +
 tools/tests/x86_emulator/test_x86_emulator.c|  4 ++
 xen/arch/x86/hvm/emulate.c  |  4 +-
 xen/arch/x86/mm.c   |  2 +
 xen/arch/x86/mm/shadow/common.c |  5 +--
 xen/arch/x86/traps.c|  1 +
 xen/arch/x86/x86_emulate/x86_emulate.c  | 51 ++---
 xen/arch/x86/x86_emulate/x86_emulate.h  |  3 ++
 8 files changed, 29 insertions(+), 43 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index 8488816..65c5a3b 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -484,6 +484,8 @@ static bool in_longmode(struct x86_emulate_ctxt *ctxt)
 
 static void set_sizes(struct x86_emulate_ctxt *ctxt)
 {
+ctxt->lma = long_mode_active(ctxt);
+
 if ( in_longmode(ctxt) )
 ctxt->addr_size = ctxt->sp_size = 64;
 else
diff --git a/tools/tests/x86_emulator/test_x86_emulator.c 
b/tools/tests/x86_emulator/test_x86_emulator.c
index 5be8ddc..efeb175 100644
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -319,6 +319,7 @@ int main(int argc, char **argv)
 ctxt.regs = 
 ctxt.force_writeback = 0;
 ctxt.vendor= X86_VENDOR_UNKNOWN;
+ctxt.lma   = sizeof(void *) == 8;
 ctxt.addr_size = 8 * sizeof(void *);
 ctxt.sp_size   = 8 * sizeof(void *);
 
@@ -2922,6 +2923,7 @@ int main(int argc, char **argv)
 {
 decl_insn(vzeroupper);
 
+ctxt.lma = false;
 ctxt.sp_size = ctxt.addr_size = 32;
 
 asm volatile ( "vxorps %xmm2, %xmm2, %xmm3\n"
@@ -2949,6 +2951,7 @@ int main(int argc, char **argv)
 goto fail;
 printf("okay\n");
 
+ctxt.lma = true;
 ctxt.sp_size = ctxt.addr_size = 64;
 }
 else
@@ -3001,6 +3004,7 @@ int main(int argc, char **argv)
 continue;
 
 memcpy(res, blobs[j].code, blobs[j].size);
+ctxt.lma = blobs[j].bitness == 64;
 ctxt.addr_size = ctxt.sp_size = blobs[j].bitness;
 
 if ( ctxt.addr_size == sizeof(void *) * CHAR_BIT )
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 39e4319..a4918e1 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -2044,7 +2044,9 @@ void hvm_emulate_init_per_insn(
 unsigned int pfec = PFEC_page_present;
 unsigned long addr;
 
-if ( hvm_long_mode_active(curr) &&
+hvmemul_ctxt->ctxt.lma = hvm_long_mode_active(curr);
+
+if ( hvmemul_ctxt->ctxt.lma &&
  hvmemul_ctxt->seg_reg[x86_seg_cs].attr.fields.l )
 hvmemul_ctxt->ctxt.addr_size = hvmemul_ctxt->ctxt.sp_size = 64;
 else
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 3918a37..d010aa3 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -5412,6 +5412,7 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
 .vendor = d->arch.cpuid->x86_vendor,
 .addr_size = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
 .sp_size   = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
+.lma = true,
 },
 };
 int rc;
@@ -5566,6 +5567,7 @@ int mmio_ro_do_page_fault(struct vcpu *v, unsigned long 
addr,
 .vendor = v->domain->arch.cpuid->x86_vendor,
 .addr_size = addr_size,
 .sp_size = addr_size,
+.lma = true,
 .data = _ro_ctxt
 };
 int rc;
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 736ceaa..d432198 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -326,15 +326,14 @@ const struct x86_emulate_ops *shadow_init_emulation(
 
 sh_ctxt->ctxt.regs = regs;
 sh_ctxt->ctxt.vendor = v->domain->arch.cpuid->x86_vendor;
+sh_ctxt->ctxt.lma = hvm_long_mode_active(v);
 
 /* Segment cache initialisation. Primed with CS. */
 creg = hvm_get_seg_reg(x86_seg_cs, sh_ctxt);
 
 /* Work out the emulation mode. */
-if ( hvm_long_mode_active(v) && creg->attr.fields.l )
-{
+

[Xen-devel] [PATCH v2 for-4.9 5/6] x86/emul: Drop swint_emulate infrastructure

2017-04-05 Thread Andrew Cooper
With the SVM injection logic capable of doing its own emulation, there is no
need for this hardware-specific assistance in the common emulator.

Signed-off-by: Andrew Cooper 
Reviewed-by: Paul Durrant 
Reviewed-by: Jan Beulich 
---
CC: Tim Deegan 
CC: Julien Grall 

v2:
 * imm8 -> imm1
---
 tools/fuzz/x86_instruction_emulator/fuzz-emul.c |  18 +--
 xen/arch/x86/hvm/emulate.c  |   7 -
 xen/arch/x86/mm.c   |   2 -
 xen/arch/x86/mm/shadow/common.c |   1 -
 xen/arch/x86/x86_emulate/x86_emulate.c  | 187 
 xen/arch/x86/x86_emulate/x86_emulate.h  |  53 ---
 6 files changed, 30 insertions(+), 238 deletions(-)

diff --git a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c 
b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
index 890642c..8488816 100644
--- a/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
+++ b/tools/fuzz/x86_instruction_emulator/fuzz-emul.c
@@ -536,8 +536,7 @@ enum {
 HOOK_put_fpu,
 HOOK_invlpg,
 HOOK_vmfunc,
-OPTION_swint_emulation, /* Two bits */
-CANONICALIZE_rip = OPTION_swint_emulation + 2,
+CANONICALIZE_rip,
 CANONICALIZE_rsp,
 CANONICALIZE_rbp
 };
@@ -577,19 +576,6 @@ static void disable_hooks(void)
 MAYBE_DISABLE_HOOK(invlpg);
 }
 
-static void set_swint_support(struct x86_emulate_ctxt *ctxt)
-{
-unsigned int swint_opt = (input.options >> OPTION_swint_emulation) & 3;
-static const enum x86_swint_emulation map[4] = {
-x86_swint_emulate_none,
-x86_swint_emulate_none,
-x86_swint_emulate_icebp,
-x86_swint_emulate_all
-};
-
-ctxt->swint_emulate = map[swint_opt];
-}
-
 /*
  * Constrain input to architecturally-possible states where
  * the emulator relies on these
@@ -693,8 +679,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t 
size)
 
 disable_hooks();
 
-set_swint_support();
-
 do {
 /* FIXME: Until we actually implement SIGFPE handling properly */
 setup_fpu_exception_handler();
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 87ca801..39e4319 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -2033,13 +2033,6 @@ void hvm_emulate_init_once(
 hvmemul_ctxt->ctxt.regs = regs;
 hvmemul_ctxt->ctxt.vendor = curr->domain->arch.cpuid->x86_vendor;
 hvmemul_ctxt->ctxt.force_writeback = true;
-
-if ( cpu_has_vmx )
-hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
-else if ( cpu_has_svm_nrips )
-hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_icebp;
-else
-hvmemul_ctxt->ctxt.swint_emulate = x86_swint_emulate_all;
 }
 
 void hvm_emulate_init_per_insn(
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index be4e308..3918a37 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -5412,7 +5412,6 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
 .vendor = d->arch.cpuid->x86_vendor,
 .addr_size = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
 .sp_size   = is_pv_32bit_domain(d) ? 32 : BITS_PER_LONG,
-.swint_emulate = x86_swint_emulate_none,
 },
 };
 int rc;
@@ -5567,7 +5566,6 @@ int mmio_ro_do_page_fault(struct vcpu *v, unsigned long 
addr,
 .vendor = v->domain->arch.cpuid->x86_vendor,
 .addr_size = addr_size,
 .sp_size = addr_size,
-.swint_emulate = x86_swint_emulate_none,
 .data = _ro_ctxt
 };
 int rc;
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 574337c..736ceaa 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -326,7 +326,6 @@ const struct x86_emulate_ops *shadow_init_emulation(
 
 sh_ctxt->ctxt.regs = regs;
 sh_ctxt->ctxt.vendor = v->domain->arch.cpuid->x86_vendor;
-sh_ctxt->ctxt.swint_emulate = x86_swint_emulate_none;
 
 /* Segment cache initialisation. Primed with CS. */
 creg = hvm_get_seg_reg(x86_seg_cs, sh_ctxt);
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c 
b/xen/arch/x86/x86_emulate/x86_emulate.c
index 7af8a42..8c4e885 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1999,142 +1999,6 @@ static bool umip_active(struct x86_emulate_ctxt *ctxt,
(cr4 & X86_CR4_UMIP);
 }
 
-/* Inject a software interrupt/exception, emulating if needed. */
-static int inject_swint(enum x86_swint_type type,
-uint8_t vector, uint8_t insn_len,
-struct x86_emulate_ctxt *ctxt,
-const struct x86_emulate_ops *ops)
-{
-int rc, error_code, fault_type = EXC_GP;
-
-/*
- * Without hardware support, injecting software interrupts/exceptions is
- * problematic.
- *
- * All software methods of generating 

  1   2   3   4   >