|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4 5/9] tools/libxc: common code
On 07/05/14 17:08, Ian Campbell wrote:
> On Wed, 2014-05-07 at 15:38 +0100, Andrew Cooper wrote:
>> On 07/05/14 14:03, Ian Campbell wrote:
>>> On Wed, 2014-04-30 at 19:36 +0100, Andrew Cooper wrote:
>>>> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
>>>> Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
>>>> Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx>
>>>> ---
>>>> tools/libxc/saverestore/common.c | 87 ++++++
>>>> tools/libxc/saverestore/common.h | 172 ++++++++++++
>>>> tools/libxc/saverestore/common_x86.c | 54 ++++
>>>> tools/libxc/saverestore/common_x86.h | 21 ++
>>>> tools/libxc/saverestore/common_x86_hvm.c | 53 ++++
>>>> tools/libxc/saverestore/common_x86_pv.c | 431
>>>> ++++++++++++++++++++++++++++++
>>>> tools/libxc/saverestore/common_x86_pv.h | 104 +++++++
>>>> tools/libxc/saverestore/restore.c | 288 ++++++++++++++++++++
>>>> tools/libxc/saverestore/save.c | 42 +++
>>>> 9 files changed, 1252 insertions(+)
>>>> create mode 100644 tools/libxc/saverestore/common_x86.c
>>>> create mode 100644 tools/libxc/saverestore/common_x86.h
>>>> create mode 100644 tools/libxc/saverestore/common_x86_hvm.c
>>>> create mode 100644 tools/libxc/saverestore/common_x86_pv.c
>>>> create mode 100644 tools/libxc/saverestore/common_x86_pv.h
>>>>
>>>> diff --git a/tools/libxc/saverestore/common.c
>>>> b/tools/libxc/saverestore/common.c
>>>> index de2e727..b159c4c 100644
>>>> --- a/tools/libxc/saverestore/common.c
>>>> +++ b/tools/libxc/saverestore/common.c
>>>> @@ -1,3 +1,5 @@
>>>> +#include <assert.h>
>>>> +
>>>> #include "common.h"
>>>>
>>>> static const char *dhdr_types[] =
>>>> @@ -52,6 +54,91 @@ const char *rec_type_to_str(uint32_t type)
>>>> return "Reserved";
>>>> }
>>>>
>>>> +int write_split_record(struct context *ctx, struct record *rec,
>>>> + void *buf, size_t sz)
>>>> +{
>>>> + static const char zeroes[7] = { 0 };
>>>> + xc_interface *xch = ctx->xch;
>>>> + uint32_t combined_length = rec->length + sz;
>>>> + size_t record_length = (combined_length + 7) & ~7UL;
>>> Isn't this ROUNDUP(combined_length, 3)? (Where 3 and/or 7 perhaps ought
>>> to be given names)
>> It is. I am not certain that 3/7 need specific named, given the
>> specification mandating that all records have trailing 0s to align the
>> subsequent record on an 8 byte boundary.
> If the specification mandates it then that is an argument *for* a
> SAVE_RECORD_ALIGNMENT type #define.
Fair enough. I will include that.
>>>> + datasz = (rhdr.length + 7) & ~7U;
>>> Another ROUNDUP and #define XXX 3 or 7 opportunity. (I'm not going to
>>> mention any more of these I find).
>>>
>>> Is it not a bug in the input for datasz to not be aligned? I thought you
>>> were padding everything.
>> It is certainly not a bug. For the blobs which can have an arbitrary
>> length, the record length field reflects the exact length. Trailing 0s
>> are then inserted into the stream to align the start of the next record
>> on an 8 byte boundary.
> Make sense. In which case can you add a comment /* Include padding not
> covered by rhdr.length */ or some such.
Ok.
>
>>>> +// Hack out junk from the namespace
>>> ... namespace, because/in order to...
>>>
>>> (to prevent accidents I suppose?)
>> because mfn_to_pfn and pfn_to_mfn are gross abortions of macros which
>> look like regular functions but take implicit scoped state.
> So don't use them?
But the names themselves are the only logical choice for real functions
of the same purpose.
>
>
>> I have been collapsing patches from 3 separate people ;) I will do a
>> consistency check before this becomes non-rfc.
> nb: these patches are missing the RFC tag if that's what they are.
The RFC tag appears to have dropped off some time during formatting
them. My appologies. The series as a whole is still not functionally
complete but is getting there.
>
>>>> @@ -0,0 +1,431 @@
>>>> +#include <assert.h>
>>>> +
>>>> +#include "common_x86_pv.h"
>>>> +
>>>> +xen_pfn_t mfn_to_pfn(struct context *ctx, xen_pfn_t mfn)
>>>> +{
>>>> + assert(mfn <= ctx->x86_pv.max_mfn);
>>> Just to confirm that anywhere there is an assert like this then if it is
>>> based on potentially user controller input then it has already been
>>> validated elsewhere first? (with the abstraction I couldn't spot where
>>> that was)
>> It is validated in every case I am aware of, usually by
>> "mfn_in_pseudophysmap()"
> Good, because it would be a security issue if not...
In what way? The absolute worst that could happen is a controlled stop
of the process handling migration for this domain.
It is certainly better than walking off the end of the mapped m2p.
>
>>>> + switch ( type )
>>>> + {
>>>> + case XEN_DOMCTL_PFINFO_L4TAB:
>>>> + ERROR("??? Found L4 table for 32bit guest");
>>>> + errno = EINVAL;
>>>> + return -1;
>>>> +
>>>> + case XEN_DOMCTL_PFINFO_L3TAB:
>>>> + /* 32bit guests can only use the first 4 entries of their L3
>>>> tables.
>>>> + * All other are potentially used by Xen. */
>>>> + xen_first = 4;
>>>> + xen_last = 512;
>>>> + break;
>>>> +
>>>> + case XEN_DOMCTL_PFINFO_L2TAB:
>>>> + /* It is hard to spot Xen mappings in a 32bit guest's L2.
>>>> Most
>>>> + * are normal but only a few will have Xen mappings.
>>> Internally Xen has PGT_pae_xen_l2, I wonder if it could be coaxed into
>>> exposing that here too?
>> That would require exposing xen struct page_info's for specific mfns.
>> This way seems less hacky.
> I meant via the introduction of XEN_DOMCTL_PFIINF_L2XENTAB (name TBD)
> (AIUI this interface is essentially exposing that bit of the page info,
> isn't it?)
Hmm. There are some spare numbers available to be used. It might be an
idea.
>
>>>> ... normalize_page
>>>> + local_page = malloc(PAGE_SIZE);
>>> How bad is the overhead of (what I pressume are) all these allocs and
>>> frees? (I've not come across the caller in this patch, maybe it will
>>> become clear later).
>>>
>>> Would it be worth keeping an array around shadowing the "live" batch of
>>> pages?
>> The allocation and freeing of pages has allowed valgrind to be
>> fantastically useful at pointing out when my code was doing something silly.
> Fair enough (I wonder if there is some valgrind mechanism for marking
> memory as explicitly uninitialised as if it had been freed/reallocated)
I have searched but cant find anything. As valgrind is designed to wrap
compiled binaries, making function calls into it is probably non-trivial.
>>>> +
>>>> + if ( nr_pages > 0 )
>>>> + {
>>>> + mapping = guest_page = xc_map_foreign_bulk(
>>>> + xch, ctx->domid, PROT_READ | PROT_WRITE,
>>>> + mfns, map_errs, nr_pages);
>>>> + if ( !mapping )
>>>> + {
>>>> + PERROR("Unable to map %u mfns for %u pages of data",
>>>> + nr_pages, count);
>>>> + goto err;
>>>> + }
>>>> + }
>>>> +
>>>> + for ( i = 0, j = 0; i < count; ++i )
>>>> + {
>>>> + switch ( types[i] )
>>>> + {
>>>> + case XEN_DOMCTL_PFINFO_XTAB:
>>>> + case XEN_DOMCTL_PFINFO_BROKEN:
>>>> + /* Nothing at all to do */
>>> Is this a deliberate fall-thru? Please comment if so.
>>>
>>>> + case XEN_DOMCTL_PFINFO_XALLOC:
>>>> + /* Nothing futher to do */
>>> "further"
>> They are all fall-though, indicated by the continue on the next line,
>> and lack of default.
> The existing comment half way through the list is what breaks this
> though, since it's no longer clear that it does indicate that.
The comment is partially stale in this context anyway (following
refactoring). I shall see about collapsing it down to a single if
statement which can be made to be more clear.
>
>>>> + for ( i = 0; i < pages->count; ++i )
>>>> + {
>>>> + pfn = pages->pfn[i] & PAGE_DATA_PFN_MASK;
>>>> + if ( !ctx->ops.pfn_is_valid(ctx, pfn) )
>>>> + {
>>>> + ERROR("pfn %#lx (index %u) outside domain maximum", pfn, i);
>>>> + goto err;
>>>> + }
>>>> +
>>>> + type = (pages->pfn[i] & PAGE_DATA_TYPE_MASK) >> 32;
>>>> + if ( ((type >> XEN_DOMCTL_PFINFO_LTAB_SHIFT) >= 5) &&
>>>> + ((type >> XEN_DOMCTL_PFINFO_LTAB_SHIFT) <= 8) )
>>> What are 5 and 8?
>>>
>>> This might all be clearer with the use of a #define or two, and perhaps
>>> using a switch over the expected valid types and explicitly invalid
>>> types.
>> 5 to 8 are the "holes" in the otherwise complete PFINFO_TYPE numerspace.
>>
>> My views are that the XEN_DOMCTL_PFINFO_* macros are unconditionally
>> horrible to use, whatever you are trying to do, which is why the use of
>> them is gauged for local clarity rather than global consistency.
>>
>> I am not sure a switch statement would help here.
> In that case a comment would help.
I might be able to make it a little clearer.
>
>>>> diff --git a/tools/libxc/saverestore/save.c
>>>> b/tools/libxc/saverestore/save.c
>>>> index c013e62..e842e6c 100644
>>>> --- a/tools/libxc/saverestore/save.c
>>>> +++ b/tools/libxc/saverestore/save.c
>>>> @@ -1,5 +1,47 @@
>>>> +#include <arpa/inet.h>
>>>> +
>>>> #include "common.h"
>>>>
>>>> +int write_headers(struct context *ctx, uint16_t guest_type)
>>>> +{
>>>> + xc_interface *xch = ctx->xch;
>>>> + int32_t xen_version = xc_version(xch, XENVER_version, NULL);
>>>> + struct ihdr ihdr =
>>>> + {
>>> I think coding style puts this on the previous line and the body should
>>> be 4 spaces further in.
>> Not according to the emacs mode at the bottom, which would appear to
>> create a contradiction in CODING_SYTLE.
> CODING_STYLE would take precedence if it said anything about this
> specific case, which it doesn't. The prevailing style everywhere else I
> could find was with the { on the same line.
>
> (not sure which bit of the emacs marker you think contradicts this,
> BSD's style(9) doesn't cover this case either)
>
> Ian.
>
That would be emacs' cc-mode interpretation of the marker, when
instructed to indent the entire file.
If it isn't specifically covered in BSD's style(9), I am sure there are
multiple interpretations going. I will see about persuading emacs not
to indent them.
~Andrew
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |