From: "Michael S. Tsirkin" <mst@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Baoquan He <bhe@redhat.com>,
Sergio Lopez Pascual <slp@redhat.com>,
"Somlo, Gabriel" <somlo@cmu.edu>,
xiaolong.ye@intel.com
Subject: Re: [PATCH v14 8/9] fw_cfg: write vmcoreinfo details
Date: Thu, 15 Feb 2018 20:35:33 +0200 [thread overview]
Message-ID: <20180215203418-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <CAMxuvawaNA_yWE86Rv5abgLrdduYeJrc5Ezf63-F0HRhRjO=3Q@mail.gmail.com>
On Thu, Feb 15, 2018 at 07:24:34PM +0100, Marc-André Lureau wrote:
> Hi
>
> On Thu, Feb 15, 2018 at 7:09 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Wed, Feb 14, 2018 at 03:18:49PM +0100, Marc-André Lureau wrote:
> >> If the "etc/vmcoreinfo" fw_cfg file is present and we are not running
> >> the kdump kernel, write the addr/size of the vmcoreinfo ELF note.
> >>
> >> The DMA operation is expected to run synchronously with today qemu,
> >> but the specification states that it may become async, so we run
> >> "control" field check in a loop for eventual changes.
> >>
> >> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >> ---
> >> drivers/firmware/qemu_fw_cfg.c | 144 ++++++++++++++++++++++++++++++++++++++++-
> >> 1 file changed, 141 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
> >> index 37638b95cb45..69939e2529f2 100644
> >> --- a/drivers/firmware/qemu_fw_cfg.c
> >> +++ b/drivers/firmware/qemu_fw_cfg.c
> >> @@ -34,11 +34,17 @@
> >> #include <linux/io.h>
> >> #include <linux/ioport.h>
> >> #include <linux/fw_cfg.h>
> >> +#include <linux/delay.h>
> >> +#include <linux/crash_dump.h>
> >> +#include <linux/crash_core.h>
> >>
> >> MODULE_AUTHOR("Gabriel L. Somlo <somlo@cmu.edu>");
> >> MODULE_DESCRIPTION("QEMU fw_cfg sysfs support");
> >> MODULE_LICENSE("GPL");
> >>
> >> +/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
> >> +static u32 fw_cfg_rev;
> >> +
> >> /* fw_cfg device i/o register addresses */
> >> static bool fw_cfg_is_mmio;
> >> static phys_addr_t fw_cfg_p_base;
> >> @@ -59,6 +65,65 @@ static inline u16 fw_cfg_sel_endianness(u16 key)
> >> (u16 __force)cpu_to_le16(key);
> >> }
> >>
> >> +static inline bool fw_cfg_dma_enabled(void)
> >> +{
> >> + return (fw_cfg_rev & FW_CFG_VERSION_DMA) && fw_cfg_reg_dma;
> >> +}
> >> +
> >> +/* qemu fw_cfg device is sync today, but spec says it may become async */
> >> +static void fw_cfg_wait_for_control(struct fw_cfg_dma_access *d)
> >> +{
> >> + do {
> >> + u32 ctrl = be32_to_cpu(READ_ONCE(d->control));
> >> +
> >> + if ((ctrl & ~FW_CFG_DMA_CTL_ERROR) == 0)
> >> + return;
> >> +
> >> + usleep_range(50, 100);
> >
> > I would just do cpu_relax() here.
>
> ok, I didn't know that one.
>
> >
> >> + } while (true);
Pls write for (;;) and not do - while (true).
> >> +
> >> + /* do not reorder the read to d->control */
> >> + rmb();
> >
> > Hmm. I don't really understand the comment.
> > Is this code ever reacheable? How does it help?
>
> I thought that's what you suggested in v13 review, but true, I should
> replace the return with a break to reach it. Is that what you expect
> too?
I'd do it unconditionally after reading ctrl.
> (my understanding is to make sure the READ_ONCE(control) in
> wait_for_control happens before READ_ONCE(control) after in
> dma_transfer)
I expect you to understand memory-barriers.txt :)
> >
> >> +}
> >> +
> >> +static ssize_t fw_cfg_dma_transfer(void *address, u32 length, u32 control)
> >> +{
> >> + phys_addr_t dma;
> >> + struct fw_cfg_dma_access *d = NULL;
> >> + ssize_t ret = length;
> >> +
> >> + d = kmalloc(sizeof(*d), GFP_KERNEL);
> >> + if (!d) {
> >> + ret = -ENOMEM;
> >> + goto end;
> >> + }
> >> +
> >> + /* fw_cfg device does not need IOMMU protection, so use physical addresses */
> >> + *d = (struct fw_cfg_dma_access) {
> >> + .address = cpu_to_be64(address ? virt_to_phys(address) : 0),
> >> + .length = cpu_to_be32(length),
> >> + .control = cpu_to_be32(control)
> >> + };
> >> +
> >> + dma = virt_to_phys(d);
> >> +
> >> + iowrite32be((u64)dma >> 32, fw_cfg_reg_dma);
> >> + /* force memory to sync before notifying device via MMIO */
> >> + wmb();
> >> + iowrite32be(dma, fw_cfg_reg_dma + 4);
> >> +
> >> + fw_cfg_wait_for_control(d);
> >> +
> >> + if (be32_to_cpu(READ_ONCE(d->control)) & FW_CFG_DMA_CTL_ERROR) {
> >> + ret = -EIO;
> >> + }
> >> +
> >> +end:
> >> + kfree(d);
> >> +
> >> + return ret;
> >> +}
> >> +
> >> /* read chunk of given fw_cfg blob (caller responsible for sanity-check) */
> >> static inline void fw_cfg_read_blob(u16 key,
> >> void *buf, loff_t pos, size_t count)
> >> @@ -87,6 +152,47 @@ static inline void fw_cfg_read_blob(u16 key,
> >> acpi_release_global_lock(glk);
> >> }
> >>
> >> +#ifdef CONFIG_CRASH_CORE
> >> +/* write chunk of given fw_cfg blob (caller responsible for sanity-check) */
> >> +static ssize_t fw_cfg_write_blob(u16 key,
> >> + void *buf, loff_t pos, size_t count)
> >> +{
> >> + u32 glk = -1U;
> >> + acpi_status status;
> >> + ssize_t ret = count;
> >> +
> >> + /* If we have ACPI, ensure mutual exclusion against any potential
> >> + * device access by the firmware, e.g. via AML methods:
> >> + */
> >> + status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk);
> >> + if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) {
> >> + /* Should never get here */
> >> + WARN(1, "%s: Failed to lock ACPI!\n", __func__);
> >> + return -EINVAL;
> >> + }
> >> +
> >> + mutex_lock(&fw_cfg_dev_lock);
> >> + if (pos == 0) {
> >> + ret = fw_cfg_dma_transfer(buf, count, key << 16
> >> + | FW_CFG_DMA_CTL_SELECT
> >> + | FW_CFG_DMA_CTL_WRITE);
> >> + } else {
> >> + iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl);
> >> + ret = fw_cfg_dma_transfer(NULL, pos, FW_CFG_DMA_CTL_SKIP);
> >> + if (ret < 0)
> >> + goto end;
> >> + ret = fw_cfg_dma_transfer(buf, count, FW_CFG_DMA_CTL_WRITE);
> >> + }
> >> +
> >> +end:
> >> + mutex_unlock(&fw_cfg_dev_lock);
> >> +
> >> + acpi_release_global_lock(glk);
> >> +
> >> + return ret;
> >> +}
> >> +#endif /* CONFIG_CRASH_CORE */
> >> +
> >> /* clean up fw_cfg device i/o */
> >> static void fw_cfg_io_cleanup(void)
> >> {
> >> @@ -185,9 +291,6 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev)
> >> return 0;
> >> }
> >>
> >> -/* fw_cfg revision attribute, in /sys/firmware/qemu_fw_cfg top-level dir. */
> >> -static u32 fw_cfg_rev;
> >> -
> >> static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf)
> >> {
> >> return sprintf(buf, "%u\n", fw_cfg_rev);
> >> @@ -210,6 +313,32 @@ struct fw_cfg_sysfs_entry {
> >> struct list_head list;
> >> };
> >>
> >> +#ifdef CONFIG_CRASH_CORE
> >> +static ssize_t fw_cfg_write_vmcoreinfo(const struct fw_cfg_file *f)
> >> +{
> >> + static struct fw_cfg_vmcoreinfo *data;
> >> + ssize_t ret;
> >> +
> >> + data = kmalloc(sizeof(struct fw_cfg_vmcoreinfo), GFP_KERNEL);
> >> + if (!data)
> >> + return -ENOMEM;
> >> +
> >> + *data = (struct fw_cfg_vmcoreinfo) {
> >> + .guest_format = cpu_to_le16(FW_CFG_VMCOREINFO_FORMAT_ELF),
> >> + .size = cpu_to_le32(VMCOREINFO_NOTE_SIZE),
> >> + .paddr = cpu_to_le64(paddr_vmcoreinfo_note())
> >> + };
> >> + /* spare ourself reading host format support for now since we
> >> + * don't know what else to format - host may ignore ours
> >> + */
> >> + ret = fw_cfg_write_blob(be16_to_cpu(f->select), data,
> >> + 0, sizeof(struct fw_cfg_vmcoreinfo));
> >> +
> >> + kfree(data);
> >> + return ret;
> >> +}
> >> +#endif /* CONFIG_CRASH_CORE */
> >> +
> >> /* get fw_cfg_sysfs_entry from kobject member */
> >> static inline struct fw_cfg_sysfs_entry *to_entry(struct kobject *kobj)
> >> {
> >> @@ -450,6 +579,15 @@ static int fw_cfg_register_file(const struct fw_cfg_file *f)
> >> int err;
> >> struct fw_cfg_sysfs_entry *entry;
> >>
> >> +#ifdef CONFIG_CRASH_CORE
> >> + if (fw_cfg_dma_enabled() &&
> >> + strcmp(f->name, FW_CFG_VMCOREINFO_FILENAME) == 0 &&
> >> + !is_kdump_kernel()) {
> >> + if (fw_cfg_write_vmcoreinfo(f) < 0)
> >> + pr_warn("fw_cfg: failed to write vmcoreinfo");
> >> + }
> >> +#endif
> >> +
> >> /* allocate new entry */
> >> entry = kzalloc(sizeof(*entry), GFP_KERNEL);
> >> if (!entry)
> >> --
> >> 2.16.1.73.g5832b7e9f2
next prev parent reply other threads:[~2018-02-15 18:35 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-14 14:18 [PATCH v14 0/9] fw_cfg: add DMA operations & etc/vmcoreinfo support Marc-André Lureau
2018-02-14 14:18 ` [PATCH v14 1/9] crash: export paddr_vmcoreinfo_note() Marc-André Lureau
2018-02-14 14:18 ` [PATCH v14 2/9] fw_cfg: add a public uapi header Marc-André Lureau
2018-02-14 19:37 ` Michael S. Tsirkin
2018-02-15 9:29 ` Marc-Andre Lureau
2018-02-15 18:22 ` Michael S. Tsirkin
2018-02-14 20:41 ` Michael S. Tsirkin
2018-02-15 9:25 ` Marc-Andre Lureau
2018-02-15 18:20 ` Michael S. Tsirkin
2018-02-15 18:33 ` Marc-André Lureau
2018-02-14 14:18 ` [PATCH v14 3/9] fw_cfg: fix sparse warnings in fw_cfg_sel_endianness() Marc-André Lureau
2018-02-14 20:46 ` Michael S. Tsirkin
2018-02-15 9:34 ` Marc-Andre Lureau
2018-02-15 18:25 ` Michael S. Tsirkin
2018-02-14 14:18 ` [PATCH v14 4/9] fw_cfg: fix sparse warnings with fw_cfg_file Marc-André Lureau
2018-02-14 14:18 ` [PATCH v14 5/9] fw_cfg: fix sparse warning reading FW_CFG_ID Marc-André Lureau
2018-02-14 14:18 ` [PATCH v14 6/9] fw_cfg: fix sparse warnings around FW_CFG_FILE_DIR read Marc-André Lureau
2018-02-14 14:18 ` [PATCH v14 7/9] fw_cfg: add DMA register Marc-André Lureau
2018-02-14 14:18 ` [PATCH v14 8/9] fw_cfg: write vmcoreinfo details Marc-André Lureau
2018-02-15 18:09 ` Michael S. Tsirkin
2018-02-15 18:24 ` Marc-André Lureau
2018-02-15 18:35 ` Michael S. Tsirkin [this message]
2018-02-14 14:18 ` [PATCH v14 9/9] RFC: fw_cfg: do DMA read operation Marc-André Lureau
2018-02-14 16:48 ` Michael S. Tsirkin
2018-02-14 16:52 ` Marc-Andre Lureau
2018-02-14 16:59 ` Michael S. Tsirkin
2018-02-14 17:08 ` Marc-Andre Lureau
2018-02-14 17:12 ` Michael S. Tsirkin
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=20180215203418-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=bhe@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=marcandre.lureau@redhat.com \
--cc=slp@redhat.com \
--cc=somlo@cmu.edu \
--cc=xiaolong.ye@intel.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.