From: Richard Henderson <richard.henderson@linaro.org>
To: Peter Maydell <peter.maydell@linaro.org>,
qemu-arm@nongnu.org, qemu-devel@nongnu.org
Cc: "Philippe Mathieu-Daudé" <f4bug@amsat.org>
Subject: Re: [PATCH for-6.0 v2 4/5] hw/core/loader: Add new function rom_ptr_for_as()
Date: Thu, 18 Mar 2021 12:44:21 -0600 [thread overview]
Message-ID: <176ca6cf-f917-eb5d-a5ce-d8a98db8fce4@linaro.org> (raw)
In-Reply-To: <20210318174823.18066-5-peter.maydell@linaro.org>
On 3/18/21 11:48 AM, Peter Maydell wrote:
> For accesses to rom blob data before or during reset, we have a
> function rom_ptr() which looks for a rom blob that would be loaded to
> the specified address, and returns a pointer into the rom blob data
> corresponding to that address. This allows board or CPU code to say
> "what is the data that is going to be loaded to this address?".
>
> However, this function does not take account of memory region
> aliases. If for instance a machine model has RAM at address
> 0x0000_0000 which is aliased to also appear at 0x1000_0000, a
> rom_ptr() query for address 0x0000_0000 will only return a match if
> the guest image provided by the user was loaded at 0x0000_0000 and
> not if it was loaded at 0x1000_0000, even though they are the same
> RAM and a run-time guest CPU read of 0x0000_0000 will read the data
> loaded to 0x1000_0000.
>
> Provide a new function rom_ptr_for_as() which takes an AddressSpace
> argument, so that it can check whether the MemoryRegion corresponding
> to the address is also mapped anywhere else in the AddressSpace and
> look for rom blobs that loaded to that alias.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> include/hw/loader.h | 31 +++++++++++++++++++
> hw/core/loader.c | 75 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 106 insertions(+)
>
> diff --git a/include/hw/loader.h b/include/hw/loader.h
> index a9eeea39521..cbfc1848737 100644
> --- a/include/hw/loader.h
> +++ b/include/hw/loader.h
> @@ -290,6 +290,37 @@ void rom_transaction_end(bool commit);
>
> int rom_copy(uint8_t *dest, hwaddr addr, size_t size);
> void *rom_ptr(hwaddr addr, size_t size);
> +/**
> + * rom_ptr_for_as: Return a pointer to ROM blob data for the address
> + * @as: AddressSpace to look for the ROM blob in
> + * @addr: Address within @as
> + * @size: size of data required in bytes
> + *
> + * Returns: pointer into the data which backs the matching ROM blob,
> + * or NULL if no blob covers the address range.
> + *
> + * This function looks for a ROM blob which covers the specified range
> + * of bytes of length @size starting at @addr within the address space
> + * @as. This is useful for code which runs as part of board
> + * initialization or CPU reset which wants to read data that is part
> + * of a user-supplied guest image or other guest memory contents, but
> + * which runs before the ROM loader's reset function has copied the
> + * blobs into guest memory.
> + *
> + * rom_ptr_for_as() will look not just for blobs loaded directly to
> + * the specified address, but also for blobs which were loaded to an
> + * alias of the region at a different location in the AddressSpace.
> + * In other words, if a machine model has RAM at address 0x0000_0000
> + * which is aliased to also appear at 0x1000_0000, rom_ptr_for_as()
> + * will return the correct data whether the guest image was linked and
> + * loaded at 0x0000_0000 or 0x1000_0000. Contrast rom_ptr(), which
> + * will only return data if the image load address is an exact match
> + * with the queried address.
> + *
> + * New code should prefer to use rom_ptr_for_as() instead of
> + * rom_ptr().
> + */
> +void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size);
> void hmp_info_roms(Monitor *mon, const QDict *qdict);
>
> #define rom_add_file_fixed(_f, _a, _i) \
> diff --git a/hw/core/loader.c b/hw/core/loader.c
> index 9feca32de98..d3e5f3b423f 100644
> --- a/hw/core/loader.c
> +++ b/hw/core/loader.c
> @@ -1383,6 +1383,81 @@ void *rom_ptr(hwaddr addr, size_t size)
> return rom->data + (addr - rom->addr);
> }
>
> +typedef struct FindRomCBData {
> + size_t size; /* Amount of data we want from ROM, in bytes */
> + MemoryRegion *mr; /* MR at the unaliased guest addr */
> + hwaddr xlat; /* Offset of addr within mr */
> + void *rom; /* Output: rom data pointer, if found */
> +} FindRomCBData;
> +
> +static bool find_rom_cb(Int128 start, Int128 len, const MemoryRegion *mr,
> + hwaddr offset_in_region, void *opaque)
> +{
> + FindRomCBData *cbdata = opaque;
> + hwaddr alias_addr;
> +
> + if (mr != cbdata->mr) {
> + return false;
> + }
> +
> + alias_addr = int128_get64(start) + cbdata->xlat - offset_in_region;
> + cbdata->rom = rom_ptr(alias_addr, cbdata->size);
> + if (!cbdata->rom) {
> + return false;
> + }
> + /* Found a match, stop iterating */
> + return true;
> +}
> +
> +void *rom_ptr_for_as(AddressSpace *as, hwaddr addr, size_t size)
> +{
> + /*
> + * Find any ROM data for the given guest address range. If there
> + * is a ROM blob then return a pointer to the host memory
> + * corresponding to 'addr'; otherwise return NULL.
> + *
> + * We look not only for ROM blobs that were loaded directly to
> + * addr, but also for ROM blobs that were loaded to aliases of
> + * that memory at other addresses within the AddressSpace.
> + *
> + * Note that we do not check @as against the 'as' member in the
> + * 'struct Rom' returned by rom_ptr(). The Rom::as is the
> + * AddressSpace which the rom blob should be written to, whereas
> + * our @as argument is the AddressSpace which we are (effectively)
> + * reading from, and the same underlying RAM will often be visible
> + * in multiple AddressSpaces. (A common example is a ROM blob
> + * written to the 'system' address space but then read back via a
> + * CPU's cpu->as pointer.) This does mean we might potentially
> + * return a false-positive match if a ROM blob was loaded into an
> + * AS which is entirely separate and distinct from the one we're
> + * querying, but this issue exists also for rom_ptr() and hasn't
> + * caused any problems in practice.
> + */
> + FlatView *fv;
> + void *rom;
> + hwaddr len_unused;
> + FindRomCBData cbdata = {};
> +
> + /* Easy case: there's data at the actual address */
> + rom = rom_ptr(addr, size);
> + if (rom) {
> + return rom;
> + }
Should you really have this special case? Nowhere is this going to verify that
@addr is in @as.
Otherwise,
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
r~
> +
> + RCU_READ_LOCK_GUARD();
> +
> + fv = address_space_to_flatview(as);
> + cbdata.mr = flatview_translate(fv, addr, &cbdata.xlat, &len_unused,
> + false, MEMTXATTRS_UNSPECIFIED);
> + if (!cbdata.mr) {
> + /* Nothing at this address, so there can't be any aliasing */
> + return NULL;
> + }
> + cbdata.size = size;
> + flatview_for_each_range(fv, find_rom_cb, &cbdata);
> + return cbdata.rom;
> +}
> +
> void hmp_info_roms(Monitor *mon, const QDict *qdict)
> {
> Rom *rom;
>
next prev parent reply other threads:[~2021-03-18 18:47 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-18 17:48 [PATCH for-6.0 v2 0/5] arm: Make M-profile VTOR loads on reset handle memory aliasin Peter Maydell
2021-03-18 17:48 ` [PATCH for-6.0 v2 1/5] memory: Make flatview_cb return bool, not int Peter Maydell
2021-03-18 18:39 ` Richard Henderson
2021-03-18 20:55 ` Philippe Mathieu-Daudé
2021-03-18 17:48 ` [PATCH for-6.0 v2 2/5] memory: Document flatview_for_each_range() Peter Maydell
2021-03-18 18:40 ` Richard Henderson
2021-03-18 20:58 ` Philippe Mathieu-Daudé
2021-03-18 17:48 ` [PATCH for-6.0 v2 3/5] memory: Add offset_in_region to flatview_cb arguments Peter Maydell
2021-03-18 18:40 ` Richard Henderson
2021-03-18 21:01 ` Philippe Mathieu-Daudé
2021-03-18 17:48 ` [PATCH for-6.0 v2 4/5] hw/core/loader: Add new function rom_ptr_for_as() Peter Maydell
2021-03-18 18:44 ` Richard Henderson [this message]
2021-03-18 19:02 ` Peter Maydell
2021-03-18 21:14 ` Richard Henderson
2021-03-18 21:28 ` Peter Maydell
2021-03-18 21:56 ` Richard Henderson
2021-03-18 17:48 ` [PATCH for-6.0 v2 5/5] target/arm: Make M-profile VTOR loads on reset handle memory aliasing Peter Maydell
2021-03-18 18:44 ` Richard Henderson
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=176ca6cf-f917-eb5d-a5ce-d8a98db8fce4@linaro.org \
--to=richard.henderson@linaro.org \
--cc=f4bug@amsat.org \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.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).