From: Tamas K Lengyel <tamas.lengyel@zentific.com>
To: Tim Deegan <tim@xen.org>
Cc: Ian Campbell <ian.campbell@citrix.com>,
Julien Grall <julien.grall@linaro.org>,
Ian Jackson <ian.jackson@eu.citrix.com>,
"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>,
Stefano Stabellini <stefano.stabellini@citrix.com>,
Andres Lagar-Cavilla <andres@lagarcavilla.org>,
Jan Beulich <jbeulich@suse.com>,
Daniel De Graaf <dgdegra@tycho.nsa.gov>,
Tamas K Lengyel <tklengyel@sec.in.tum.de>
Subject: Re: [PATCH for-4.5 v7 07/21] xen: Relocate p2m_mem_access_check into common and refactor it.
Date: Thu, 18 Sep 2014 12:47:19 +0200 [thread overview]
Message-ID: <CAErYnsgj8jid5E8_WK-c-WRAnxBSbEdhbmwCL9_Nkpc8jjYWGA@mail.gmail.com> (raw)
In-Reply-To: <20140918103908.GC65000@deinos.phlegethon.org>
[-- Attachment #1.1: Type: text/plain, Size: 8135 bytes --]
On Thu, Sep 18, 2014 at 12:39 PM, Tim Deegan <tim@xen.org> wrote:
> Hi,
>
> Thanks for the patch. Tidying this up is a great idea but I'm afraid
> it can't be done quite this way.
>
> At 22:51 +0200 on 17 Sep (1410990670), Tamas K Lengyel wrote:
> > The p2m_mem_access_check was used only to automatically promote the
> > special-case mem_access rights and to allocate the mem_access message.
> > In this patch we abstract the violation check into a common
> mem_access_check
> > function and change its return value to int.
> >
> > Return with rc < 0 means the fault wasn't triggered by mem_access
> permissions.
> > Return with rc == 0 it was but rights were not automatically promoted.
> > Return with rc > 0 means mem_access rights had been automatically
> promoted.
> >
> > As part of this patch, we relocate the x86/mm/mm-locks.h header into asm
> > as to be able to create a generic inlined p2m_gpfn_lock/unlock wrapper
> > that each arch can define based on its locking scheme.
>
> I'm afraid not. mm-locks.h is hidden away in arch/x86/mm
> deliberately, to stop p2m internals from leaking out into the rest of
> the code and making it harder to reason about. So the fact that you
> had to move it suggests that we need to think about using cleaner
> interfaces between the code you're extracting and the rest of the p2m
> code...
>
> > +int mem_access_check(paddr_t gpa, unsigned long gla, struct npfec npfec)
> > +{
> > + bool_t violation;
> > + mfn_t mfn;
> > + p2m_access_t p2ma;
> > + p2m_type_t p2mt;
> > + mem_event_request_t *req;
> > + int rc;
> > + struct vcpu *v = current;
> > + unsigned long gfn = gpa >> PAGE_SHIFT;
> > + struct domain *d = v->domain;
> > + struct p2m_domain* p2m = p2m_get_hostp2m(d);
> > +
> > + /* First, handle rx2rw conversion automatically.
> > + * These calls to p2m->set_entry() must succeed: we have the gfn
> > + * locked and just did a successful get_entry(). */
> > + p2m_gpfn_lock(p2m, gfn);
> > + mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL);
>
> Neither of these (direct access to a p2m lock or direct call of a p2m
> function pointer) should happen outside the p2m code.
>
> From an outside caller you _could_ use get_gfn_type_access(p2m, gfn,
> &p2mt, &p2ma, 0, NULL) instead (and put_gfn() instead of
> p2m_gpfn_unlock()). But directly calling p2m->set_entry() (or
> p2m_set_entry()) is still not OK.
>
> I think it would be better to leave an arch-specific
> "bool_t p2m_mem_access_check(p2m, gfn, npfec, &p2ma)" that does the
> lookup and the automatic promotions and returns the access type. It
> should also do the check for missing listeners and automatically reset
> p2m entries (i.e. the second call to ->set_entry() below). Then this
> function won't need to take any locks or get_gfn calls at all -- it
> will just have the check for non-vioating faults, the call to
> p2m_mem_access_check() that might ajdust entries, and the code to
> prepare a req.
>
> > +
> > + /* Check if the access is against the permissions. */
> > + switch ( p2ma )
> > + {
> > + case p2m_access_rwx:
> > + violation = 0;
> > + break;
> > + case p2m_access_rw:
> > + violation = npfec.insn_fetch;
> > + break;
> > + case p2m_access_wx:
> > + violation = npfec.read_access;
> > + break;
> > + case p2m_access_rx:
> > + case p2m_access_rx2rw:
> > + violation = npfec.write_access;
> > + break;
> > + case p2m_access_x:
> > + violation = npfec.read_access || npfec.write_access;
> > + break;
> > + case p2m_access_w:
> > + violation = npfec.read_access || npfec.insn_fetch;
> > + break;
> > + case p2m_access_r:
> > + violation = npfec.write_access || npfec.insn_fetch;
> > + break;
> > + case p2m_access_n:
> > + case p2m_access_n2rwx:
> > + default:
> > + violation = npfec.read_access || npfec.write_access ||
> npfec.insn_fetch;
> > + break;
> > + }
>
> In any case this block, which doesn't depend on the p2m contents at
> all, should happen before any locks or lookups. That way you can
> avoid taking the locks at all for non-violating faults (as the
> original code does).
>
> > + /* If no violation is found here, it needs to be reinjected. */
> > + if ( !violation )
> > + {
> > + p2m_gpfn_unlock(p2m, gfn);
> > + return -EFAULT;
> > + }
> > +
> > + /* Check for automatic setting promotion. */
> > + if ( npfec.write_access && p2ma == p2m_access_rx2rw )
> > + {
> > + rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, p2mt,
> p2m_access_rw);
> > + ASSERT(rc == 0);
> > + p2m_gpfn_unlock(p2m, gfn);
> > + return 1;
> > + }
> > + else if ( p2ma == p2m_access_n2rwx )
> > + {
> > + ASSERT(npfec.write_access || npfec.read_access ||
> npfec.insn_fetch);
> > + rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
> > + p2mt, p2m_access_rwx);
> > + ASSERT(rc == 0);
> > + }
> > + p2m_gpfn_unlock(p2m, gfn);
> > +
> > + /* Otherwise, check if there is a memory event listener, and send
> the message along */
> > + if ( !mem_event_check_ring(&d->mem_event->access) )
> > + {
> > + /* No listener */
> > + if ( p2m->access_required )
> > + {
> > + gdprintk(XENLOG_INFO, "Memory access permissions failure, "
> > + "no mem_event listener VCPU %d, dom
> %d\n",
> > + v->vcpu_id, d->domain_id);
> > + domain_crash(v->domain);
> > + return -EFAULT;
> > + }
> > + else
> > + {
> > + p2m_gpfn_lock(p2m, gfn);
> > + mfn = p2m->get_entry(p2m, gfn, &p2mt, &p2ma, 0, NULL);
> > + if ( p2ma != p2m_access_n2rwx )
> > +
> > + {
> > + /* A listener is not required, so clear the access
> > + * restrictions. This set must succeed: we have the
> > + * gfn locked and just did a successful get_entry(). */
> > + rc = p2m->set_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
> > + p2mt, p2m_access_rwx);
> > + ASSERT(rc == 0);
> > + }
> > + p2m_gpfn_unlock(p2m, gfn);
> > + return 1;
> > + }
> > + }
> > +
> > + req = xzalloc(mem_event_request_t);
> > + if ( req )
> > + {
> > + req->reason = MEM_EVENT_REASON_VIOLATION;
> > +
> > + /* Pause the current VCPU */
> > + if ( p2ma != p2m_access_n2rwx )
> > + req->flags |= MEM_EVENT_FLAG_VCPU_PAUSED;
> > +
> > + /* Send request to mem event */
> > + req->gfn = gfn;
> > + req->offset = gpa & ((1 << PAGE_SHIFT) - 1);
> > + req->gla_valid = npfec.gla_valid;
> > + req->gla = gla;
> > + if ( npfec.kind == npfec_kind_with_gla )
> > + req->fault_with_gla = 1;
> > + else if ( npfec.kind == npfec_kind_in_gpt )
> > + req->fault_in_gpt = 1;
> > + req->access_r = npfec.read_access;
> > + req->access_w = npfec.write_access;
> > + req->access_x = npfec.insn_fetch;
> > + req->vcpu_id = v->vcpu_id;
> > +
> > + mem_access_send_req(v->domain, req);
>
> The original function returned the req for the caller to send, and the
> caller delayed sending it until the end of hvm_hap_nested_page_fault(),
> when the last locks are dropped. You need to keep this behaviour or
> the system can deadlock.
>
> I wonder whether we could add an ASSERT_NOT_IN_ATOMIC() at the top of
> mem_event_wait_slot() to make this kind of thing easier to spot. At
> the moment it will only fail if it actually has to wait.
>
> Cheers,
>
> Tim.
>
Ack. I think I'll drop this patch for the time being as the refactoring
work required for it to be in common mem_access is quite significant, both
in the x86 and the ARM side. And it would only result in a bit of
code-deduplication. We could pick-it up later if there is a need for it /
value in it.
Thanks,
Tamas
[-- Attachment #1.2: Type: text/html, Size: 9785 bytes --]
[-- Attachment #2: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2014-09-18 10:47 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-17 20:51 [PATCH for-4.5 v7 00/21] Mem_event and mem_access for ARM Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 01/21] xen: Relocate mem_access and mem_event into common Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 02/21] xen: Relocate struct npfec definition " Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 03/21] xen: Relocate mem_event_op domctl and access_op memop " Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 04/21] xen: Relocate set_access_required domctl " Tamas K Lengyel
2014-09-18 9:18 ` Jan Beulich
2014-09-18 10:36 ` Tamas K Lengyel
2014-09-18 10:37 ` Tamas K Lengyel
2014-09-18 11:17 ` Tim Deegan
2014-09-18 11:21 ` Tamas K Lengyel
2014-09-18 12:34 ` Jan Beulich
2014-09-18 13:02 ` Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 05/21] xen: Relocate p2m_access_t into common and swap the order Tamas K Lengyel
2014-09-18 9:22 ` Jan Beulich
2014-09-18 10:52 ` Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 06/21] xen: Relocate p2m_mem_access_resume to mem_access common Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 07/21] xen: Relocate p2m_mem_access_check into common and refactor it Tamas K Lengyel
2014-09-18 9:28 ` Jan Beulich
2014-09-18 10:39 ` Tim Deegan
2014-09-18 10:47 ` Tamas K Lengyel [this message]
2014-09-18 11:13 ` Tim Deegan
2014-09-22 12:08 ` Ian Campbell
2014-09-17 20:51 ` [PATCH for-4.5 v7 08/21] x86/p2m: Typo fix for spelling ambiguous Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 09/21] x86/p2m: Fix conversion macro of p2m_access to XENMEM_access Tamas K Lengyel
2014-09-18 9:35 ` Jan Beulich
2014-09-18 9:41 ` Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 10/21] xen/mem_event: Clean out superfluous white-spaces Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 11/21] xen/mem_event: Relax error condition on debug builds Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 12/21] xen/mem_event: Abstract architecture specific sanity checks Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 13/21] xen/mem_access: Abstract architecture specific sanity check Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 14/21] xen/arm: p2m changes for mem_access support Tamas K Lengyel
2014-09-22 12:20 ` Ian Campbell
2014-09-22 17:16 ` Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 15/21] xen/arm: Implement domain_get_maximum_gpfn Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 16/21] xen/arm: Add p2m_set_permission and p2m_shatter_page helpers Tamas K Lengyel
2014-09-22 12:24 ` Ian Campbell
2014-09-22 18:24 ` Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 17/21] xen/arm: Data abort exception (R/W) mem_events Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 18/21] xen/arm: Instruction prefetch abort (X) mem_event handling Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 19/21] xen/arm: Enable the compilation of mem_access and mem_event on ARM Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 20/21] tools/libxc: Allocate magic page for mem access " Tamas K Lengyel
2014-09-17 20:51 ` [PATCH for-4.5 v7 21/21] tools/tests: Enable xen-access " Tamas K Lengyel
2014-09-22 12:29 ` Ian Campbell
2014-09-22 17:11 ` Tamas K Lengyel
2014-09-23 8:37 ` Ian Campbell
2014-09-18 9:21 ` [PATCH for-4.5 v7 00/21] Mem_event and mem_access for ARM Tim Deegan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAErYnsgj8jid5E8_WK-c-WRAnxBSbEdhbmwCL9_Nkpc8jjYWGA@mail.gmail.com \
--to=tamas.lengyel@zentific.com \
--cc=andres@lagarcavilla.org \
--cc=dgdegra@tycho.nsa.gov \
--cc=ian.campbell@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=jbeulich@suse.com \
--cc=julien.grall@linaro.org \
--cc=stefano.stabellini@citrix.com \
--cc=tim@xen.org \
--cc=tklengyel@sec.in.tum.de \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).