* Re: [PATCH v6 1/2] mm: Add MREMAP_DONTUNMAP to mremap().
From: Kirill A. Shutemov @ 2020-02-20 11:57 UTC (permalink / raw)
To: Brian Geffon
Cc: Andrew Morton, Michael S . Tsirkin, Arnd Bergmann, linux-kernel,
linux-mm, linux-api, Andy Lutomirski, Will Deacon,
Andrea Arcangeli, Sonny Rao, Minchan Kim, Joel Fernandes, Yu Zhao,
Jesse Barnes, Florian Weimer
In-Reply-To: <20200218173221.237674-1-bgeffon@google.com>
On Tue, Feb 18, 2020 at 09:32:20AM -0800, Brian Geffon wrote:
> When remapping an anonymous, private mapping, if MREMAP_DONTUNMAP is
> set, the source mapping will not be removed. The remap operation
> will be performed as it would have been normally by moving over the
> page tables to the new mapping. The old vma will have any locked
> flags cleared, have no pagetables, and any userfaultfds that were
> watching that range will continue watching it.
>
> For a mapping that is shared or not anonymous, MREMAP_DONTUNMAP will cause
> the mremap() call to fail. Because MREMAP_DONTUNMAP always results in moving
> a VMA you MUST use the MREMAP_MAYMOVE flag. The final result is two
> equally sized VMAs where the destination contains the PTEs of the source.
>
> We hope to use this in Chrome OS where with userfaultfd we could write
> an anonymous mapping to disk without having to STOP the process or worry
> about VMA permission changes.
>
> This feature also has a use case in Android, Lokesh Gidra has said
> that "As part of using userfaultfd for GC, We'll have to move the physical
> pages of the java heap to a separate location. For this purpose mremap
> will be used. Without the MREMAP_DONTUNMAP flag, when I mremap the java
> heap, its virtual mapping will be removed as well. Therefore, we'll
> require performing mmap immediately after. This is not only time consuming
> but also opens a time window where a native thread may call mmap and
> reserve the java heap's address range for its own usage. This flag
> solves the problem."
>
> v5 -> v6:
> - Code cleanup suggested by Kirill.
>
> v4 -> v5:
> - Correct commit message to more accurately reflect the behavior.
> - Clear VM_LOCKED and VM_LOCKEDONFAULT on the old vma.
>
> Signed-off-by: Brian Geffon <bgeffon@google.com>
> ---
> include/uapi/linux/mman.h | 5 +-
> mm/mremap.c | 103 ++++++++++++++++++++++++++++++--------
> 2 files changed, 85 insertions(+), 23 deletions(-)
>
> diff --git a/include/uapi/linux/mman.h b/include/uapi/linux/mman.h
> index fc1a64c3447b..923cc162609c 100644
> --- a/include/uapi/linux/mman.h
> +++ b/include/uapi/linux/mman.h
> @@ -5,8 +5,9 @@
> #include <asm/mman.h>
> #include <asm-generic/hugetlb_encode.h>
>
> -#define MREMAP_MAYMOVE 1
> -#define MREMAP_FIXED 2
> +#define MREMAP_MAYMOVE 1
> +#define MREMAP_FIXED 2
> +#define MREMAP_DONTUNMAP 4
>
> #define OVERCOMMIT_GUESS 0
> #define OVERCOMMIT_ALWAYS 1
> diff --git a/mm/mremap.c b/mm/mremap.c
> index 1fc8a29fbe3f..fa27103502c5 100644
> --- a/mm/mremap.c
> +++ b/mm/mremap.c
> @@ -318,8 +318,8 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
> static unsigned long move_vma(struct vm_area_struct *vma,
> unsigned long old_addr, unsigned long old_len,
> unsigned long new_len, unsigned long new_addr,
> - bool *locked, struct vm_userfaultfd_ctx *uf,
> - struct list_head *uf_unmap)
> + bool *locked, unsigned long flags,
> + struct vm_userfaultfd_ctx *uf, struct list_head *uf_unmap)
> {
> struct mm_struct *mm = vma->vm_mm;
> struct vm_area_struct *new_vma;
> @@ -408,11 +408,46 @@ static unsigned long move_vma(struct vm_area_struct *vma,
> if (unlikely(vma->vm_flags & VM_PFNMAP))
> untrack_pfn_moved(vma);
>
> + if (unlikely(!err && (flags & MREMAP_DONTUNMAP))) {
> + if (vm_flags & VM_ACCOUNT) {
> + /* Always put back VM_ACCOUNT since we won't unmap */
> + vma->vm_flags |= VM_ACCOUNT;
> +
> + vm_acct_memory(vma_pages(new_vma));
> + }
> +
> + /*
> + * locked_vm accounting: if the mapping remained the same size
> + * it will have just moved and we don't need to touch locked_vm
> + * because we skip the do_unmap. If the mapping shrunk before
> + * being moved then the do_unmap on that portion will have
> + * adjusted vm_locked. Only if the mapping grows do we need to
> + * do something special; the reason is locked_vm only accounts
> + * for old_len, but we're now adding new_len - old_len locked
> + * bytes to the new mapping.
> + */
> + if (vm_flags & VM_LOCKED && new_len > old_len) {
> + mm->locked_vm += (new_len - old_len) >> PAGE_SHIFT;
> + *locked = true;
> + }
> +
> + /* We always clear VM_LOCKED[ONFAULT] on the old vma */
> + vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
> +
> + goto out;
> + }
> +
> if (do_munmap(mm, old_addr, old_len, uf_unmap) < 0) {
> /* OOM: unable to split vma, just get accounts right */
> vm_unacct_memory(excess >> PAGE_SHIFT);
> excess = 0;
> }
> +
> + if (vm_flags & VM_LOCKED) {
> + mm->locked_vm += new_len >> PAGE_SHIFT;
> + *locked = true;
> + }
> +out:
> mm->hiwater_vm = hiwater_vm;
>
> /* Restore VM_ACCOUNT if one or two pieces of vma left */
> @@ -422,16 +457,12 @@ static unsigned long move_vma(struct vm_area_struct *vma,
> vma->vm_next->vm_flags |= VM_ACCOUNT;
> }
>
> - if (vm_flags & VM_LOCKED) {
> - mm->locked_vm += new_len >> PAGE_SHIFT;
> - *locked = true;
> - }
> -
> return new_addr;
> }
>
> static struct vm_area_struct *vma_to_resize(unsigned long addr,
> - unsigned long old_len, unsigned long new_len, unsigned long *p)
> + unsigned long old_len, unsigned long new_len, unsigned long flags,
> + unsigned long *p)
> {
> struct mm_struct *mm = current->mm;
> struct vm_area_struct *vma = find_vma(mm, addr);
> @@ -453,6 +484,10 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,
> return ERR_PTR(-EINVAL);
> }
>
> + if (flags & MREMAP_DONTUNMAP && (!vma_is_anonymous(vma) ||
> + vma->vm_flags & VM_SHARED))
> + return ERR_PTR(-EINVAL);
> +
> if (is_vm_hugetlb_page(vma))
> return ERR_PTR(-EINVAL);
>
> @@ -497,7 +532,7 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,
>
> static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
> unsigned long new_addr, unsigned long new_len, bool *locked,
> - struct vm_userfaultfd_ctx *uf,
> + unsigned long flags, struct vm_userfaultfd_ctx *uf,
> struct list_head *uf_unmap_early,
> struct list_head *uf_unmap)
> {
> @@ -505,7 +540,7 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
> struct vm_area_struct *vma;
> unsigned long ret = -EINVAL;
> unsigned long charged = 0;
> - unsigned long map_flags;
> + unsigned long map_flags = 0;
>
> if (offset_in_page(new_addr))
> goto out;
> @@ -534,9 +569,11 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
> if ((mm->map_count + 2) >= sysctl_max_map_count - 3)
> return -ENOMEM;
>
> - ret = do_munmap(mm, new_addr, new_len, uf_unmap_early);
> - if (ret)
> - goto out;
> + if (flags & MREMAP_FIXED) {
> + ret = do_munmap(mm, new_addr, new_len, uf_unmap_early);
> + if (ret)
> + goto out;
> + }
>
> if (old_len >= new_len) {
> ret = do_munmap(mm, addr+new_len, old_len - new_len, uf_unmap);
> @@ -545,13 +582,26 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
> old_len = new_len;
> }
>
> - vma = vma_to_resize(addr, old_len, new_len, &charged);
> + vma = vma_to_resize(addr, old_len, new_len, flags, &charged);
> if (IS_ERR(vma)) {
> ret = PTR_ERR(vma);
> goto out;
> }
>
> - map_flags = MAP_FIXED;
> + /*
> + * MREMAP_DONTUNMAP expands by new_len - (new_len - old_len), we will
> + * check that we can expand by new_len and vma_to_resize will handle
> + * the vma growing which is (new_len - old_len).
> + */
< Sorry for delay. >
I have hard time understanding the case when new_len != old_len.
Correct me if I'm wrong, but looks like that you change the size of old
mapping to be the new_len and then create a new of the same new_len.
This doesn't look right to me.
In my opinion, MREMAP_DONTUNMAP has to leave the old mapping intact. And
create the new mapping adjusted to the new_len.
Other option is to force new_len == old_len if MREMAP_DONTUNMAP is
specified. It would simplify the implementation. And I don't see why
anybody would really want anything else.
> + if (flags & MREMAP_DONTUNMAP &&
> + !may_expand_vm(mm, vma->vm_flags, new_len >> PAGE_SHIFT)) {
> + ret = -ENOMEM;
> + goto out;
> + }
> +
> + if (flags & MREMAP_FIXED)
> + map_flags |= MAP_FIXED;
> +
> if (vma->vm_flags & VM_MAYSHARE)
> map_flags |= MAP_SHARED;
>
> @@ -561,10 +611,16 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
> if (offset_in_page(ret))
> goto out1;
>
> - ret = move_vma(vma, addr, old_len, new_len, new_addr, locked, uf,
> + /* We got a new mapping */
> + if (!(flags & MREMAP_FIXED))
> + new_addr = ret;
> +
> + ret = move_vma(vma, addr, old_len, new_len, new_addr, locked, flags, uf,
> uf_unmap);
> +
> if (!(offset_in_page(ret)))
> goto out;
Not related to the effort directly, but do we really use offset_in_page()
as a substitute for IS_ERR() here. That's disgusting.
> +
> out1:
> vm_unacct_memory(charged);
>
> @@ -609,12 +665,16 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
> addr = untagged_addr(addr);
> new_addr = untagged_addr(new_addr);
>
> - if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
> + if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP))
> return ret;
>
> if (flags & MREMAP_FIXED && !(flags & MREMAP_MAYMOVE))
> return ret;
>
> + /* MREMAP_DONTUNMAP is always a move */
> + if (flags & MREMAP_DONTUNMAP && !(flags & MREMAP_MAYMOVE))
> + return ret;
> +
> if (offset_in_page(addr))
> return ret;
>
> @@ -632,9 +692,10 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
> if (down_write_killable(¤t->mm->mmap_sem))
> return -EINTR;
>
> - if (flags & MREMAP_FIXED) {
> + if (flags & (MREMAP_FIXED | MREMAP_DONTUNMAP)) {
> ret = mremap_to(addr, old_len, new_addr, new_len,
> - &locked, &uf, &uf_unmap_early, &uf_unmap);
> + &locked, flags, &uf, &uf_unmap_early,
> + &uf_unmap);
> goto out;
> }
>
> @@ -662,7 +723,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
> /*
> * Ok, we need to grow..
> */
> - vma = vma_to_resize(addr, old_len, new_len, &charged);
> + vma = vma_to_resize(addr, old_len, new_len, flags, &charged);
> if (IS_ERR(vma)) {
> ret = PTR_ERR(vma);
> goto out;
> @@ -712,7 +773,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
> }
>
> ret = move_vma(vma, addr, old_len, new_len, new_addr,
> - &locked, &uf, &uf_unmap);
> + &locked, flags, &uf, &uf_unmap);
> }
> out:
> if (offset_in_page(ret)) {
> --
> 2.25.0.265.gbab2e86ba0-goog
>
--
Kirill A. Shutemov
^ permalink raw reply
* Re: [PATCH v2 1/2] struct_union_enum_specifier: always initialize sym->scope
From: Oleg Nesterov @ 2020-02-20 11:57 UTC (permalink / raw)
To: Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse
In-Reply-To: <20200220005602.gd22zbd7c5qy4t6k@ltop.local>
On 02/20, Luc Van Oostenryck wrote:
>
> On Wed, Feb 19, 2020 at 05:29:11PM +0100, Oleg Nesterov wrote:
> > Currently it is not possible to figure out the scope of the private
> > struct/union/enum type, its ->scope is NULL because bind_symbol() is
> > not called.
> >
> > Change struct_union_enum_specifier() to set sym->scope = block_scope
> > in this case, this is what bind_symbol() does when type has a name.
>
> Thanks.
> I've just changed the comment to "used by dissect"
Great, thanks!
> because
> elsewhere the scope or toplevel()s only relevant for symbols.
Cough... can't resist ;)
Not really, see struct_union_enum_specifier()->is_outer_scope(). But
yes sure, this is only when ->ident != NULL.
Oleg.
^ permalink raw reply
* Re: [PATCH v4] iommu/vt-d: consider real PCI device when checking if mapping is needed
From: Lu Baolu @ 2020-02-20 11:58 UTC (permalink / raw)
To: Daniel Drake; +Cc: bhelgaas, linux, iommu, dwmw2, jonathan.derrick
In-Reply-To: <20200220100607.9044-1-drake@endlessm.com>
Hi,
On 2020/2/20 18:06, Daniel Drake wrote:
>> On Wed, Feb 19, 2020 at 11:40 AM Lu Baolu<baolu.lu@linux.intel.com> wrote:
>>> With respect, this is problematical. The parent and all subdevices share
>>> a single translation entry. The DMA mask should be consistent.
>>>
>>> Otherwise, for example, subdevice A has 64-bit DMA capability and uses
>>> an identity domain for DMA translation. While subdevice B has 32-bit DMA
>>> capability and is forced to switch to DMA domain. Subdevice A will be
>>> impacted without any notification.
> Looking closer, this problematic codepath may already be happening for VMD,
> under intel_iommu_add_device(). Consider this function running for a VMD
> subdevice, we hit:
>
> domain = iommu_get_domain_for_dev(dev);
>
> I can't quite grasp the code flow here, but domain->type now always seems
> to return the domain type of the real DMA device, which seems like pretty
> reasonable behaviour.
>
> if (domain->type == IOMMU_DOMAIN_DMA) {
>
> and as detailed in previous mails, the real VMD device seems to be in a DMA
> domain by default, so we continue.
>
> if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) {
>
> Now we checked the default domain type of the subdevice. This seems rather
> likely to return IDENTITY because that's effectively the default type...
>
> ret = iommu_request_dm_for_dev(dev);
> if (ret) {
> dmar_remove_one_dev_info(dev);
> dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
> domain_add_dev_info(si_domain, dev);
> dev_info(dev,
> "Device uses a private identity domain.\n");
> }
> }
>
> and now we're doing the bad stuff that Lu pointed out: we only have one
> mapping shared for all the subdevices, so if we end up changing it for one
> subdevice, we're likely to be breaking another.
Yes. Agreed.
By the way, do all subdevices stay in a same iommu group?
Best regards,
baolu
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply
* Please pull mmc mmc-2-20-2020
From: Peng Fan @ 2020-02-20 11:58 UTC (permalink / raw)
To: u-boot
Hi Tom
Please pull mmc-2-20-2020.
I redo CI with Masahiro's fix, and no issue.
------------------------------------
sdhci: code clean-up and fix cache coherency problem
enable cache snooping on mpc830x
Fix build error when MMC_WRITE disabled
------------------------------------
CI:
https://travis-ci.org/MrVan/u-boot/builds/652853505
Thanks,
Peng.
The following changes since commit f2a73d6867ef973fbb8471cc87058205999b5e5c:
Merge tag 'u-boot-stm32-20200214' of https://gitlab.denx.de/u-boot/custodians/u-boot-stm (2020-02-14 07:31:47 -0500)
are available in the Git repository at:
https://gitlab.denx.de/u-boot/custodians/u-boot-mmc.git tags/mmc-2-20-2020
for you to fetch changes up to 4155ad9aac9474610038b525da9eec8ad9afbc12:
mmc: sdhci: fix missing cache invalidation after reading by DMA (2020-02-20 15:09:57 +0800)
----------------------------------------------------------------
Bharat Kumar Reddy Gooty (1):
drivers: mmc: rpmb: Use R1 response
Jaehoon Chung (1):
mmc: fix the build error when MMC_WRITE is disabled
Masahiro Yamada (14):
mmc: sdhci-cadence: send tune request twice to work around errata
mmc: check the return value of mmc_select_mode_and_width()
mmc: remove unneeded forward declarations
dma-mapping: fix the prototype of dma_map_single()
dma-mapping: fix the prototype of dma_unmap_single()
dma-mapping: move dma_map_(un)single() to <linux/dma-mapping.h>
dma-mapping: add <asm/dma-mapping.h> for all architectures
mmc: sdhci: put the aligned buffer pointer to struct sdhci_host
mmc: sdhci: reduce code duplication for aligned buffer
mmc: sdhci: use lower_32_bit2() and upper_32_bits() for setting adma_addr
mmc: sdhci: remove unneeded casts
mmc: add mmc_get_dma_dir() helper
mmc: sdhci: use dma_map_single() instead of flush_cache() before DMA
mmc: sdhci: fix missing cache invalidation after reading by DMA
Rasmus Villemoes (1):
mmc: fsl_esdhc: actually enable cache snooping on mpc830x
arch/arc/include/asm/dma-mapping.h | 1 +
arch/arm/include/asm/dma-mapping.h | 29 +----------------------------
arch/m68k/include/asm/dma-mapping.h | 1 +
arch/microblaze/include/asm/dma-mapping.h | 1 +
arch/mips/include/asm/dma-mapping.h | 1 +
arch/nds32/include/asm/dma-mapping.h | 27 +--------------------------
arch/powerpc/include/asm/dma-mapping.h | 1 +
arch/riscv/include/asm/dma-mapping.h | 29 +----------------------------
arch/sandbox/include/asm/dma-mapping.h | 1 +
arch/sh/include/asm/dma-mapping.h | 1 +
arch/x86/include/asm/dma-mapping.h | 29 +----------------------------
arch/xtensa/include/asm/dma-mapping.h | 1 +
drivers/dma/ti/k3-udma.c | 2 +-
drivers/mmc/fsl_esdhc.c | 15 +++++++++++++--
drivers/mmc/mmc.c | 8 +++-----
drivers/mmc/rpmb.c | 5 +++++
drivers/mmc/sdhci-cadence.c | 21 +++++++++++++++++----
drivers/mmc/sdhci.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------
drivers/mmc/tmio-common.c | 5 ++---
drivers/mtd/nand/raw/denali.c | 5 ++---
drivers/net/altera_tse.c | 2 +-
drivers/net/ftmac110.c | 2 +-
drivers/net/macb.c | 4 ++--
drivers/soc/ti/k3-navss-ringacc.c | 2 +-
drivers/ufs/ufs.c | 2 +-
drivers/usb/cdns3/gadget.c | 2 +-
drivers/usb/dwc3/core.c | 8 ++++----
drivers/usb/dwc3/gadget.c | 2 +-
drivers/usb/gadget/udc/udc-core.c | 4 ++--
include/linux/dma-mapping.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/mmc.h | 6 ++++++
include/sdhci.h | 3 +++
32 files changed, 187 insertions(+), 192 deletions(-)
create mode 100644 arch/arc/include/asm/dma-mapping.h
create mode 100644 arch/m68k/include/asm/dma-mapping.h
create mode 100644 arch/microblaze/include/asm/dma-mapping.h
create mode 100644 arch/mips/include/asm/dma-mapping.h
create mode 100644 arch/powerpc/include/asm/dma-mapping.h
create mode 100644 arch/sandbox/include/asm/dma-mapping.h
create mode 100644 arch/sh/include/asm/dma-mapping.h
create mode 100644 arch/xtensa/include/asm/dma-mapping.h
create mode 100644 include/linux/dma-mapping.h
^ permalink raw reply
* [PATCH v3 3/5] powerpc/irq: Use current_stack_pointer in check_stack_overflow()
From: Michael Ellerman @ 2020-02-20 11:51 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20200220115141.2707-1-mpe@ellerman.id.au>
From: Christophe Leroy <christophe.leroy@c-s.fr>
The purpose of check_stack_overflow() is to verify that the stack has
not overflowed.
To really know whether the stack pointer is still within boundaries,
the check must be done directly on the value of r1.
So use current_stack_pointer, which returns the current value of r1,
rather than current_stack_frame() which causes a frame to be created
and then returns that value.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/435e0030e942507766cbef5bc95f906262d2ccf2.1579849665.git.christophe.leroy@c-s.fr
---
arch/powerpc/kernel/irq.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 02118c18434d..c7d6f5cdffdb 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -602,7 +602,7 @@ static inline void check_stack_overflow(void)
#ifdef CONFIG_DEBUG_STACKOVERFLOW
long sp;
- sp = current_stack_frame() & (THREAD_SIZE-1);
+ sp = current_stack_pointer & (THREAD_SIZE - 1);
/* check for stack overflow: is there less than 2KB free? */
if (unlikely(sp < 2048)) {
--
2.21.1
v3: s/get_sp()/current_stack_pointer/
^ permalink raw reply related
* Re: [PATCH v3 0/3] Dump QCOW2 metadata
From: Max Reitz @ 2020-02-20 11:58 UTC (permalink / raw)
To: Andrey Shinkevich, qemu-block; +Cc: kwolf, vsementsov, qemu-devel, armbru, den
In-Reply-To: <1578990137-308222-1-git-send-email-andrey.shinkevich@virtuozzo.com>
[-- Attachment #1.1: Type: text/plain, Size: 1174 bytes --]
On 14.01.20 09:22, Andrey Shinkevich wrote:
> The information about QCOW2 metadata allocations in an image ELF-file is
> helpful for finding issues with the image data integrity.
Sorry that I’m replying only so late – but I don’t know why we need this
in qemu, and this cover letter doesn’t provide a justification. I mean,
it isn’t too complex (from the diffstat), but wouldn’t it be better to
just have a script for this?
I suppose one reason to put it in qemu/qemu-img is that a script
wouldn’t be packaged by distributions. So if a user has a corrupted
image, with this series we could tell them to run qemu-img check -M and
put the output somewhere. With a script, we’d first have to tell them
to download the script. But then again, downloading a script (that
should be part of the qemu repository) doesn’t seem too much trouble to
me either.
So I’m curious as to whether you had a specific reason in mind when you
decided to implement this as part of qemu itself?
(I suppose the additional complexity is fully limited to the check
infrastructure, so it wouldn’t interfere with the rest of the qcow2
driver. Hm. Fair enough.)
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [RFC] Volume control across multiple registers
From: Mark Brown @ 2020-02-20 11:59 UTC (permalink / raw)
To: Dan Murphy; +Cc: lgirdwood, perex, tiwai, alsa-devel, linux-kernel
In-Reply-To: <2f74b971-4a6a-016f-8121-4da941eeccef@ti.com>
[-- Attachment #1: Type: text/plain, Size: 487 bytes --]
On Wed, Feb 19, 2020 at 03:11:47PM -0600, Dan Murphy wrote:
> I was looking at using the DAPM calls and use PGA_E and define an event but
> there really is no good way to get the current volume setting.
Store it in a variable in the driver's private data (there's a number of
examples of doing that for various controls, the process doesn't change
just because it's a volume), or if you've got a register cache it could
be just as easy to do the register reads and combine the values.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [yocto] Bitbake returning non-zero due to sstate errors
From: Paul Barker @ 2020-02-20 11:59 UTC (permalink / raw)
To: Richard Purdie; +Cc: Yocto discussion list
In-Reply-To: <bfe6eb79ff352439c3ed5d53757421dce5e0b17d.camel@linuxfoundation.org>
On Thu, 20 Feb 2020 at 11:36, Richard Purdie
<richard.purdie@linuxfoundation.org> wrote:
>
> On Thu, 2020-02-20 at 11:26 +0000, Paul Barker wrote:
> > In my new CI setup I'm using an sstate mirror which seems to have
> > some
> > occasional download issues. This results in the setscene task
> > failing.
> > For example:
> >
> > ERROR: qt3d-5.13.2+gitAUTOINC+93361f1a59-r0
> > do_package_write_ipk_setscene: Fetcher failure: Unable to find file
> > file://fd/sstate:qt3d:armv7at2hf-neon-linux-
> > gnueabi:5.13.2+gitAUTOINC+93361f1a59:r0:armv7at2hf-
> > neon:3:fda6c3edff0205b07ff176cf16771247117fa310bc65a6a1df6befc4230e0a
> > 74_package_write_ipk.tgz;downloadfilename=fd/sstate:qt3d:armv7at2hf-
> > neon-linux-gnueabi:5.13.2+gitAUTOINC+93361f1a59:r0:armv7at2hf-
> > neon:3:fda6c3edff0205b07ff176cf16771247117fa310bc65a6a1df6befc4230e0a
> > 74_package_write_ipk.tgz
> > anywhere. The paths that were searched were:
> > /builds/SanCloudLtd/sancloud-arago/build/sstate-cache
> > /builds/SanCloudLtd/sancloud-arago/build/sstate-cache
> > ERROR: qt3d-5.13.2+gitAUTOINC+93361f1a59-r0
> > do_package_write_ipk_setscene: No suitable staging package found
> > ERROR: Logfile of failure stored in:
> > /builds/SanCloudLtd/sancloud-arago/build/tmp/work/armv7at2hf-neon-
> > linux-gnueabi/qt3d/5.13.2+gitAUTOINC+93361f1a59-
> > r0/temp/log.do_package_write_ipk_setscene.10524
> > NOTE: recipe qt3d-5.13.2+gitAUTOINC+93361f1a59-r0: task
> > do_package_write_ipk_setscene: Failed
> > WARNING: Setscene task
> > (/builds/SanCloudLtd/sancloud-arago/sources/meta-qt5/recipes-
> > qt/qt5/qt3d_git.bb:do_package_write_ipk_setscene)
> > failed with exit code '1' - real task will be run instead
> >
> > As indicated in the final warning message there the real tasks run
> > since no sstate artifact is available. These tasks succeed:
> >
> > NOTE: recipe qt3d-5.13.2+gitAUTOINC+93361f1a59-r0: task
> > do_package_write_ipk: Succeeded
> >
> > The result is a successful build of the desired images. However, the
> > build is marked as a failure due to those sstate errors:
> >
> > Summary: There were 11 ERROR messages shown, returning a non-zero
> > exit code.
> >
> > Is this the expected behaviour? The final images are built correctly.
> > I can't see any simple way to mask those setscene errors but I might
> > be missing something.
> >
> > The full log can be seen at
> > https://gitlab.com/SanCloudLtd/sancloud-arago/-/jobs/443901140/raw.
> > I'm on the zeus branch here, I'll try to re-test on master later if I
> > can.
>
> We've discussed this before and it can be argued either way.
>
> Personally, I worry about why artefacts "disappear" and this is why its
> an error, files should not be disappearing part way through a build.
>
> From a bitbake perspective, a task really did fail and task failures
> are errors. The fact it was able to recover is a bonus.
>
> Perhaps it should be a warning now we have levels of warnings that are
> meaningful. Previously we threw so many, this would have been one more
> lost amongst many. I know many people don't like the behaviour.
I'm now looking into this...
In sstate_checkhashes() we mark sstate as available if
fetcher.checkstatus() succeeds. Then at a later point
sstate_setscene() calls sstate_installpkg() calls pstaging_fetch()
calls fetcher.download() to actually get the sstate artifact. If the
artifact is removed from the mirror between these two accesses (due to
an sstate mirror clean up running in parallel to a build), or if there
is an intermittent download failure we could see checkstatus() succeed
then download() fail.
I don't think we should ignore all setscene errors but in the specific
case where it's the download step that fails I think that should be a
warning. Or it could be an error by default with a variable we can set
to turn it into a warning. Does that sound reasonable? If so I'll work
up a patch.
Thanks,
Paul
^ permalink raw reply
* Re: [PATCH 04/12] drm: Nuke mode->vrefresh
From: Emil Velikov @ 2020-02-20 12:00 UTC (permalink / raw)
To: Ville Syrjala
Cc: Neil Armstrong, ML nouveau, Guido Günther, ML dri-devel,
Andrzej Hajda, Laurent Pinchart, Sam Ravnborg, Thomas Hellstrom,
Joonyoung Shim, Stefan Mavrodiev, Jerry Han, VMware Graphics,
Jagan Teki, Robert Chiras, Icenowy Zheng, Jonas Karlman,
Intel Graphics Development, Ben Skeggs, linux-amlogic,
Vincent Abriou
In-Reply-To: <20200219203544.31013-5-ville.syrjala@linux.intel.com>
On Wed, 19 Feb 2020 at 20:36, Ville Syrjala
<ville.syrjala@linux.intel.com> wrote:
>
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Get rid of mode->vrefresh and just calculate it on demand. Saves
> a bit of space and avoids the cached value getting out of sync
> with reality.
>
> Mostly done with cocci, with the following manual fixups:
> - Remove the now empty loop in drm_helper_probe_single_connector_modes()
> - Fix __MODE() macro in ch7006_mode.c
Speaking of ch7006_mode.c, it has its own "fixed vrefresh", which
doesn't seem to be used anywhere.
One could potentially nuke it, although it can be a completely separate patch.
This patch is:
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
-Emil
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply
* Re: [PATCH] gstreamer: Fix reproducibility issue around libcap
From: Richard Purdie @ 2020-02-20 12:00 UTC (permalink / raw)
To: Martin Hundebøll, openembedded-core
In-Reply-To: <f7970658-f3a4-051c-cd6b-b40d2b72b61c@geanix.com>
On Thu, 2020-02-20 at 12:56 +0100, Martin Hundebøll wrote:
> On 19/02/2020 16.23, Richard Purdie wrote:
> > Add an option to avoid builds depending on the presence of setcap
> > from the host system.
> >
> > Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
> > ---
> > .../gstreamer/gstreamer1.0/capfix.patch | 37 +++++++++++++++++++
> > .../gstreamer/gstreamer1.0_1.16.1.bb | 2 +
> > 2 files changed, 39 insertions(+)
> > create mode 100644 meta/recipes-multimedia/gstreamer/gstreamer1.0/capfix.patch
> >
> > diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0/capfix.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0/capfix.patch
> > new file mode 100644
> > index 00000000000..7ca3d5ad4a6
> > --- /dev/null
> > +++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0/capfix.patch
> > @@ -0,0 +1,37 @@
> > +Currently gstreamer configuration depends on whether setcap is found on the host
> > +system. Turn this into a configure option to make builds deterinistic.
> > +
> > +RP 2020/2/19
> > +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
> > +Upstream-Status: Pending
> > +
> > +Index: gstreamer-1.16.1/libs/gst/helpers/meson.build
> > +===================================================================
> > +--- gstreamer-1.16.1.orig/libs/gst/helpers/meson.build
> > ++++ gstreamer-1.16.1/libs/gst/helpers/meson.build
> > +@@ -73,7 +73,12 @@ if have_ptp
> > + endif
> > + endif
> > +
> > +- setcap = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap', required : false)
> > ++ setcap_feature = get_option('setcap')
> > ++ if setcap_feature.disabled()
> > ++ setcap = find_program('dontexist', required : false)
> > ++ else
> > ++ setcap = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap', required : false)
> > ++ endif
>
> I think this can be simplified by using get_option() directly for the
> "required" argument:
>
> setcap = find_program('setcap', '/usr/sbin/setcap', '/sbin/setcap',
> required : get_option('setcap'))
Yes, that looks better. I'm no meson expert, this is the first time
I've touched it.
I'd love if it someone was able to get this resolved with upstream.
I've been trying to work on getting various things fixed upstream (e.g.
some of the perl changes) but I'm having to take a practical view in
some areas. Getting the autobuilder stable/working sanely is currently
more of a priority than getting involved in a discussion with upstream
on something I know little about :/.
I've merged this patch but if anyone wants to improve it, I'm fine with
that.
Cheers,
Richard
^ permalink raw reply
* Re: [PATCH 04/12] drm: Nuke mode->vrefresh
From: Emil Velikov @ 2020-02-20 12:00 UTC (permalink / raw)
To: Ville Syrjala
Cc: Neil Armstrong, ML nouveau, Guido Günther, ML dri-devel,
Andrzej Hajda, Thierry Reding, Laurent Pinchart, Sam Ravnborg,
Thomas Hellstrom, Joonyoung Shim, Stefan Mavrodiev, Jerry Han,
VMware Graphics, Jagan Teki, Robert Chiras, Icenowy Zheng,
Jonas Karlman, Intel Graphics Development, Ben Skeggs,
linux-amlogic, Vincent Abriou, Jernej Skrabec, Purism Kernel Team,
Seung-Woo Kim, Kyungmin Park
In-Reply-To: <20200219203544.31013-5-ville.syrjala@linux.intel.com>
On Wed, 19 Feb 2020 at 20:36, Ville Syrjala
<ville.syrjala@linux.intel.com> wrote:
>
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Get rid of mode->vrefresh and just calculate it on demand. Saves
> a bit of space and avoids the cached value getting out of sync
> with reality.
>
> Mostly done with cocci, with the following manual fixups:
> - Remove the now empty loop in drm_helper_probe_single_connector_modes()
> - Fix __MODE() macro in ch7006_mode.c
Speaking of ch7006_mode.c, it has its own "fixed vrefresh", which
doesn't seem to be used anywhere.
One could potentially nuke it, although it can be a completely separate patch.
This patch is:
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
-Emil
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [Xen-devel] [PATCH 2/2] xen/mm: Introduce PG_state_uninitialised
From: Jan Beulich @ 2020-02-20 11:59 UTC (permalink / raw)
To: David Woodhouse
Cc: sstabellini@kernel.org, julien@xen.org, wl@xen.org,
konrad.wilk@oracle.com, george.dunlap@eu.citrix.com,
andrew.cooper3@citrix.com, ian.jackson@eu.citrix.com,
george.dunlap@citrix.com, jeff.kubascik@dornerworks.com,
Xia, Hongyan, stewart.hildebrand@dornerworks.com,
xen-devel@lists.xenproject.org
In-Reply-To: <f5b6325a469352585d7cf1d7d01d2dc4a2f2af8f.camel@infradead.org>
On 07.02.2020 19:04, David Woodhouse wrote:
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -488,7 +488,8 @@ void share_xen_page_with_guest(struct page_info *page, struct domain *d,
>
> page_set_owner(page, d);
> smp_wmb(); /* install valid domain ptr before updating refcnt. */
> - ASSERT((page->count_info & ~PGC_xen_heap) == 0);
> + ASSERT((page->count_info & ~PGC_xen_heap) == PGC_state_inuse ||
> + (page->count_info & ~PGC_xen_heap) == PGC_state_uninitialised);
Can uninitialized pages really make it here?
> @@ -1389,6 +1391,16 @@ static void free_heap_pages(
> ASSERT(order <= MAX_ORDER);
> ASSERT(node >= 0);
>
> + if ( page_state_is(pg, uninitialised) )
> + {
> + init_heap_pages(pg, 1 << order, need_scrub);
> + /*
> + * init_heap_pages() will call back into free_heap_pages() for
> + * each page but cannot keep recursing because each page will
> + * be set to PGC_state_inuse first.
> + */
> + return;
> + }
> spin_lock(&heap_lock);
Can you also add a blank line above here please?
> @@ -1780,11 +1792,10 @@ int query_page_offline(mfn_t mfn, uint32_t *status)
> * latter is not on a MAX_ORDER boundary, then we reserve the page by
> * not freeing it to the buddy allocator.
> */
> -static void init_heap_pages(
> - struct page_info *pg, unsigned long nr_pages)
> +static void init_heap_pages(struct page_info *pg, unsigned long nr_pages,
> + bool scrub)
Is this new parameter strictly needed, i.e. can free_heap_pages()
be called with uninitialized pages which need scrubbing? (The
code change is simple enough, and hence may warrant keeping, but
then the commit message could indicate so in case this isn't a
strict requirement.)
> @@ -2301,10 +2316,11 @@ int assign_pages(
> for ( i = 0; i < (1 << order); i++ )
> {
> ASSERT(page_get_owner(&pg[i]) == NULL);
> - ASSERT(!pg[i].count_info);
> + ASSERT(pg[i].count_info == PGC_state_inuse ||
> + pg[i].count_info == PGC_state_uninitialised);
Same question here: Can uninitialized pages make it here? If
so, wouldn't it be better to correct this, rather than having
the more permissive assertion?
> page_set_owner(&pg[i], d);
> smp_wmb(); /* Domain pointer must be visible before updating refcnt. */
> - pg[i].count_info = PGC_allocated | 1;
> + pg[i].count_info |= PGC_allocated | 1;
This is too relaxed for my taste: I understand you want to
retain page state, but I suppose other bits would want clearing
nevertheless.
> --- a/xen/include/asm-x86/mm.h
> +++ b/xen/include/asm-x86/mm.h
> @@ -72,12 +72,13 @@
> * { inuse, offlining, offlined, free, broken_offlining, broken }
> */
> #define PGC_state PG_mask(7, 9)
> -#define PGC_state_inuse PG_mask(0, 9)
> +#define PGC_state_uninitialised PG_mask(0, 9)
> #define PGC_state_offlining PG_mask(1, 9)
> #define PGC_state_offlined PG_mask(2, 9)
> #define PGC_state_free PG_mask(3, 9)
> #define PGC_state_broken_offlining PG_mask(4, 9)
> #define PGC_state_broken PG_mask(5, 9)
> +#define PGC_state_inuse PG_mask(6, 9)
Would imo be nice if this most common state was actually
either 1 or 7, for easy recognition. But the most suitable
value to pick may also depend on the outcome of one of the
comments on patch 1.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* Re: [Intel-gfx] [PATCH 04/12] drm: Nuke mode->vrefresh
From: Emil Velikov @ 2020-02-20 12:00 UTC (permalink / raw)
To: Ville Syrjala
Cc: Neil Armstrong, ML nouveau, Guido Günther, ML dri-devel,
Andrzej Hajda, Laurent Pinchart, Sam Ravnborg, Thomas Hellstrom,
Joonyoung Shim, Stefan Mavrodiev, Jerry Han, VMware Graphics,
Jagan Teki, Robert Chiras, Icenowy Zheng, Jonas Karlman,
Intel Graphics Development, Ben Skeggs, linux-amlogic,
Vincent Abriou, Jernej Skrabec, Purism Kernel Team, Seung-Woo Kim,
Kyungmin Park
In-Reply-To: <20200219203544.31013-5-ville.syrjala@linux.intel.com>
On Wed, 19 Feb 2020 at 20:36, Ville Syrjala
<ville.syrjala@linux.intel.com> wrote:
>
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Get rid of mode->vrefresh and just calculate it on demand. Saves
> a bit of space and avoids the cached value getting out of sync
> with reality.
>
> Mostly done with cocci, with the following manual fixups:
> - Remove the now empty loop in drm_helper_probe_single_connector_modes()
> - Fix __MODE() macro in ch7006_mode.c
Speaking of ch7006_mode.c, it has its own "fixed vrefresh", which
doesn't seem to be used anywhere.
One could potentially nuke it, although it can be a completely separate patch.
This patch is:
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
-Emil
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply
* Re: [PATCH 04/12] drm: Nuke mode->vrefresh
From: Emil Velikov @ 2020-02-20 12:00 UTC (permalink / raw)
To: Ville Syrjala
Cc: Neil Armstrong, ML nouveau, Guido Günther, ML dri-devel,
Andrzej Hajda, Thierry Reding, Laurent Pinchart, Sam Ravnborg,
Thomas Hellstrom, Joonyoung Shim, Stefan Mavrodiev, Jerry Han,
VMware Graphics, Jagan Teki, Robert Chiras, Icenowy Zheng,
Jonas Karlman, Intel Graphics Development, Ben Skeggs,
linux-amlogic, Vincent Abriou, Jernej Skrabec, Purism Kernel Team,
Seung-Woo Kim, Kyungmin Park
In-Reply-To: <20200219203544.31013-5-ville.syrjala@linux.intel.com>
On Wed, 19 Feb 2020 at 20:36, Ville Syrjala
<ville.syrjala@linux.intel.com> wrote:
>
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Get rid of mode->vrefresh and just calculate it on demand. Saves
> a bit of space and avoids the cached value getting out of sync
> with reality.
>
> Mostly done with cocci, with the following manual fixups:
> - Remove the now empty loop in drm_helper_probe_single_connector_modes()
> - Fix __MODE() macro in ch7006_mode.c
Speaking of ch7006_mode.c, it has its own "fixed vrefresh", which
doesn't seem to be used anywhere.
One could potentially nuke it, although it can be a completely separate patch.
This patch is:
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
-Emil
_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic
^ permalink raw reply
* Re: [RFC] Volume control across multiple registers
From: Mark Brown @ 2020-02-20 11:59 UTC (permalink / raw)
To: Dan Murphy; +Cc: linux-kernel, alsa-devel, tiwai, lgirdwood
In-Reply-To: <2f74b971-4a6a-016f-8121-4da941eeccef@ti.com>
[-- Attachment #1: Type: text/plain, Size: 487 bytes --]
On Wed, Feb 19, 2020 at 03:11:47PM -0600, Dan Murphy wrote:
> I was looking at using the DAPM calls and use PGA_E and define an event but
> there really is no good way to get the current volume setting.
Store it in a variable in the driver's private data (there's a number of
examples of doing that for various controls, the process doesn't change
just because it's a volume), or if you've got a register cache it could
be just as easy to do the register reads and combine the values.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v3 4/5] powerpc/irq: use IS_ENABLED() in check_stack_overflow()
From: Michael Ellerman @ 2020-02-20 11:51 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <20200220115141.2707-1-mpe@ellerman.id.au>
From: Christophe Leroy <christophe.leroy@c-s.fr>
Instead of #ifdef, use IS_ENABLED(CONFIG_DEBUG_STACKOVERFLOW).
This enable GCC to check for code validity even when the option
is not selected.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/98855694e9e8993673af08cc2e97e16e0cf50f4a.1579849665.git.christophe.leroy@c-s.fr
---
arch/powerpc/kernel/irq.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index c7d6f5cdffdb..46d5852fb00a 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -599,9 +599,11 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
static inline void check_stack_overflow(void)
{
-#ifdef CONFIG_DEBUG_STACKOVERFLOW
long sp;
+ if (!IS_ENABLED(CONFIG_DEBUG_STACKOVERFLOW))
+ return;
+
sp = current_stack_pointer & (THREAD_SIZE - 1);
/* check for stack overflow: is there less than 2KB free? */
@@ -609,7 +611,6 @@ static inline void check_stack_overflow(void)
pr_err("do_IRQ: stack overflow: %ld\n", sp);
dump_stack();
}
-#endif
}
void __do_irq(struct pt_regs *regs)
--
2.21.1
^ permalink raw reply related
* [kvm-unit-tests PATCH v5 05/10] s390x: export the clock get_clock_ms() utility
From: Pierre Morel @ 2020-02-20 12:00 UTC (permalink / raw)
To: kvm; +Cc: linux-s390, frankja, david, thuth, cohuck
In-Reply-To: <1582200043-21760-1-git-send-email-pmorel@linux.ibm.com>
Let's move get_clock_ms() to lib/s390/asm/time.h, so it can be used in
multiple places.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
---
lib/s390x/asm/time.h | 26 ++++++++++++++++++++++++++
s390x/intercept.c | 11 +----------
2 files changed, 27 insertions(+), 10 deletions(-)
create mode 100644 lib/s390x/asm/time.h
diff --git a/lib/s390x/asm/time.h b/lib/s390x/asm/time.h
new file mode 100644
index 0000000..25c7a3c
--- /dev/null
+++ b/lib/s390x/asm/time.h
@@ -0,0 +1,26 @@
+/*
+ * Clock utilities for s390
+ *
+ * Authors:
+ * Thomas Huth <thuth@redhat.com>
+ *
+ * Copied from the s390/intercept test by:
+ * Pierre Morel <pmorel@linux.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2.
+ */
+#ifndef _ASM_S390X_TIME_H_
+#define _ASM_S390X_TIME_H_
+
+static inline uint64_t get_clock_ms(void)
+{
+ uint64_t clk;
+
+ asm volatile(" stck %0 " : : "Q"(clk) : "memory");
+
+ /* Bit 51 is incrememented each microsecond */
+ return (clk >> (63 - 51)) / 1000;
+}
+
+#endif
diff --git a/s390x/intercept.c b/s390x/intercept.c
index 5f46b82..2e38257 100644
--- a/s390x/intercept.c
+++ b/s390x/intercept.c
@@ -14,6 +14,7 @@
#include <asm/interrupt.h>
#include <asm/page.h>
#include <asm/facility.h>
+#include <asm/time.h>
static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
@@ -153,16 +154,6 @@ static void test_testblock(void)
check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
}
-static uint64_t get_clock_ms(void)
-{
- uint64_t clk;
-
- asm volatile(" stck %0 " : : "Q"(clk) : "memory");
-
- /* Bit 51 is incrememented each microsecond */
- return (clk >> (63 - 51)) / 1000;
-}
-
struct {
const char *name;
void (*func)(void);
--
2.17.0
^ permalink raw reply related
* [kvm-unit-tests PATCH v5 04/10] s390x: interrupt registration
From: Pierre Morel @ 2020-02-20 12:00 UTC (permalink / raw)
To: kvm; +Cc: linux-s390, frankja, david, thuth, cohuck
In-Reply-To: <1582200043-21760-1-git-send-email-pmorel@linux.ibm.com>
Let's make it possible to add and remove a custom io interrupt handler,
that can be used instead of the normal one.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
---
lib/s390x/interrupt.c | 22 +++++++++++++++++++++-
lib/s390x/interrupt.h | 7 +++++++
2 files changed, 28 insertions(+), 1 deletion(-)
create mode 100644 lib/s390x/interrupt.h
diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c
index 3a40cac..f6f0665 100644
--- a/lib/s390x/interrupt.c
+++ b/lib/s390x/interrupt.c
@@ -10,9 +10,9 @@
* under the terms of the GNU Library General Public License version 2.
*/
#include <libcflat.h>
-#include <asm/interrupt.h>
#include <asm/barrier.h>
#include <sclp.h>
+#include <interrupt.h>
static bool pgm_int_expected;
static bool ext_int_expected;
@@ -144,12 +144,32 @@ void handle_mcck_int(void)
stap(), lc->mcck_old_psw.addr);
}
+static void (*io_int_func)(void);
+
void handle_io_int(void)
{
+ if (*io_int_func)
+ return (*io_int_func)();
report_abort("Unexpected io interrupt: on cpu %d at %#lx",
stap(), lc->io_old_psw.addr);
}
+int register_io_int_func(void (*f)(void))
+{
+ if (io_int_func)
+ return -1;
+ io_int_func = f;
+ return 0;
+}
+
+int unregister_io_int_func(void (*f)(void))
+{
+ if (io_int_func != f)
+ return -1;
+ io_int_func = NULL;
+ return 0;
+}
+
void handle_svc_int(void)
{
report_abort("Unexpected supervisor call interrupt: on cpu %d at %#lx",
diff --git a/lib/s390x/interrupt.h b/lib/s390x/interrupt.h
new file mode 100644
index 0000000..e945ef7
--- /dev/null
+++ b/lib/s390x/interrupt.h
@@ -0,0 +1,7 @@
+#ifndef __INTERRUPT_H
+#include <asm/interrupt.h>
+
+int register_io_int_func(void (*f)(void));
+int unregister_io_int_func(void (*f)(void));
+
+#endif
--
2.17.0
^ permalink raw reply related
* [kvm-unit-tests PATCH v5 02/10] s390x: Use PSW bits definitions in cstart
From: Pierre Morel @ 2020-02-20 12:00 UTC (permalink / raw)
To: kvm; +Cc: linux-s390, frankja, david, thuth, cohuck
In-Reply-To: <1582200043-21760-1-git-send-email-pmorel@linux.ibm.com>
This patch defines the PSW bits EA/BA used to initialize the PSW masks
for exceptions.
Since some PSW mask definitions exist already in arch_def.h we add these
definitions there.
We move all PSW definitions together and protect assembler code against
C syntax.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
lib/s390x/asm/arch_def.h | 15 +++++++++++----
s390x/cstart64.S | 15 ++++++++-------
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
index 15a4d49..69a8256 100644
--- a/lib/s390x/asm/arch_def.h
+++ b/lib/s390x/asm/arch_def.h
@@ -10,15 +10,21 @@
#ifndef _ASM_S390X_ARCH_DEF_H_
#define _ASM_S390X_ARCH_DEF_H_
+#define PSW_MASK_EXT 0x0100000000000000UL
+#define PSW_MASK_DAT 0x0400000000000000UL
+#define PSW_MASK_PSTATE 0x0001000000000000UL
+#define PSW_MASK_BA 0x0000000080000000UL
+#define PSW_MASK_EA 0x0000000100000000UL
+
+#define PSW_EXCEPTION_MASK (PSW_MASK_EA|PSW_MASK_BA)
+
+#ifndef __ASSEMBLER__
+
struct psw {
uint64_t mask;
uint64_t addr;
};
-#define PSW_MASK_EXT 0x0100000000000000UL
-#define PSW_MASK_DAT 0x0400000000000000UL
-#define PSW_MASK_PSTATE 0x0001000000000000UL
-
#define CR0_EXTM_SCLP 0X0000000000000200UL
#define CR0_EXTM_EXTC 0X0000000000002000UL
#define CR0_EXTM_EMGC 0X0000000000004000UL
@@ -297,4 +303,5 @@ static inline uint32_t get_prefix(void)
return current_prefix;
}
+#endif /* not __ASSEMBLER__ */
#endif
diff --git a/s390x/cstart64.S b/s390x/cstart64.S
index 45da523..2885a36 100644
--- a/s390x/cstart64.S
+++ b/s390x/cstart64.S
@@ -12,6 +12,7 @@
*/
#include <asm/asm-offsets.h>
#include <asm/sigp.h>
+#include <asm/arch_def.h>
.section .init
@@ -214,19 +215,19 @@ svc_int:
.align 8
reset_psw:
- .quad 0x0008000180000000
+ .quad PSW_EXCEPTION_MASK
initial_psw:
- .quad 0x0000000180000000, clear_bss_start
+ .quad PSW_EXCEPTION_MASK, clear_bss_start
pgm_int_psw:
- .quad 0x0000000180000000, pgm_int
+ .quad PSW_EXCEPTION_MASK, pgm_int
ext_int_psw:
- .quad 0x0000000180000000, ext_int
+ .quad PSW_EXCEPTION_MASK, ext_int
mcck_int_psw:
- .quad 0x0000000180000000, mcck_int
+ .quad PSW_EXCEPTION_MASK, mcck_int
io_int_psw:
- .quad 0x0000000180000000, io_int
+ .quad PSW_EXCEPTION_MASK, io_int
svc_int_psw:
- .quad 0x0000000180000000, svc_int
+ .quad PSW_EXCEPTION_MASK, svc_int
initial_cr0:
/* enable AFP-register control, so FP regs (+BFP instr) can be used */
.quad 0x0000000000040000
--
2.17.0
^ permalink raw reply related
* [kvm-unit-tests PATCH v5 03/10] s390x: cr0: adding AFP-register control bit
From: Pierre Morel @ 2020-02-20 12:00 UTC (permalink / raw)
To: kvm; +Cc: linux-s390, frankja, david, thuth, cohuck
In-Reply-To: <1582200043-21760-1-git-send-email-pmorel@linux.ibm.com>
While adding the definition for the AFP-Register control bit, move all
existing definitions for CR0 out of the C zone to the assmbler zone to
keep the definitions concerning CR0 together.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
lib/s390x/asm/arch_def.h | 11 ++++++-----
s390x/cstart64.S | 2 +-
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
index 69a8256..863c2bf 100644
--- a/lib/s390x/asm/arch_def.h
+++ b/lib/s390x/asm/arch_def.h
@@ -18,6 +18,12 @@
#define PSW_EXCEPTION_MASK (PSW_MASK_EA|PSW_MASK_BA)
+#define CR0_EXTM_SCLP 0X0000000000000200UL
+#define CR0_EXTM_EXTC 0X0000000000002000UL
+#define CR0_EXTM_EMGC 0X0000000000004000UL
+#define CR0_EXTM_MASK 0X0000000000006200UL
+#define CR0_AFP_REG_CRTL 0x0000000000040000UL
+
#ifndef __ASSEMBLER__
struct psw {
@@ -25,11 +31,6 @@ struct psw {
uint64_t addr;
};
-#define CR0_EXTM_SCLP 0X0000000000000200UL
-#define CR0_EXTM_EXTC 0X0000000000002000UL
-#define CR0_EXTM_EMGC 0X0000000000004000UL
-#define CR0_EXTM_MASK 0X0000000000006200UL
-
struct lowcore {
uint8_t pad_0x0000[0x0080 - 0x0000]; /* 0x0000 */
uint32_t ext_int_param; /* 0x0080 */
diff --git a/s390x/cstart64.S b/s390x/cstart64.S
index 2885a36..3b59bd1 100644
--- a/s390x/cstart64.S
+++ b/s390x/cstart64.S
@@ -230,4 +230,4 @@ svc_int_psw:
.quad PSW_EXCEPTION_MASK, svc_int
initial_cr0:
/* enable AFP-register control, so FP regs (+BFP instr) can be used */
- .quad 0x0000000000040000
+ .quad CR0_AFP_REG_CRTL
--
2.17.0
^ permalink raw reply related
* [kvm-unit-tests PATCH v5 09/10] s390x: css: ssch/tsch with sense and interrupt
From: Pierre Morel @ 2020-02-20 12:00 UTC (permalink / raw)
To: kvm; +Cc: linux-s390, frankja, david, thuth, cohuck
In-Reply-To: <1582200043-21760-1-git-send-email-pmorel@linux.ibm.com>
We add a new css_lib file to contain the I/O function we may
share with different tests.
First function is the subchannel_enable() function.
When a channel is enabled we can start a SENSE ID command using
the SSCH instruction to recognize the control unit and device.
This tests the success of SSCH, the I/O interruption and the TSCH
instructions.
The test expects a device with a control unit type of 0xC0CA as the
first subchannel of the CSS.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
lib/s390x/asm/arch_def.h | 1 +
lib/s390x/asm/time.h | 10 +++
lib/s390x/css.h | 20 ++++++
lib/s390x/css_lib.c | 55 ++++++++++++++
s390x/Makefile | 1 +
s390x/css.c | 152 +++++++++++++++++++++++++++++++++++++++
6 files changed, 239 insertions(+)
create mode 100644 lib/s390x/css_lib.c
diff --git a/lib/s390x/asm/arch_def.h b/lib/s390x/asm/arch_def.h
index 863c2bf..ab3fc9d 100644
--- a/lib/s390x/asm/arch_def.h
+++ b/lib/s390x/asm/arch_def.h
@@ -10,6 +10,7 @@
#ifndef _ASM_S390X_ARCH_DEF_H_
#define _ASM_S390X_ARCH_DEF_H_
+#define PSW_MASK_IO 0x0200000000000000UL
#define PSW_MASK_EXT 0x0100000000000000UL
#define PSW_MASK_DAT 0x0400000000000000UL
#define PSW_MASK_PSTATE 0x0001000000000000UL
diff --git a/lib/s390x/asm/time.h b/lib/s390x/asm/time.h
index 25c7a3c..d3e4eab 100644
--- a/lib/s390x/asm/time.h
+++ b/lib/s390x/asm/time.h
@@ -23,4 +23,14 @@ static inline uint64_t get_clock_ms(void)
return (clk >> (63 - 51)) / 1000;
}
+static inline void delay(unsigned long ms)
+{
+ unsigned long startclk;
+
+ startclk = get_clock_ms();
+ for (;;)
+ if (get_clock_ms() - startclk > ms)
+ break;
+}
+
#endif
diff --git a/lib/s390x/css.h b/lib/s390x/css.h
index 448e597..b6ab0ba 100644
--- a/lib/s390x/css.h
+++ b/lib/s390x/css.h
@@ -97,6 +97,19 @@ struct irb {
uint32_t emw[8];
} __attribute__ ((aligned(4)));
+#define CCW_CMD_SENSE_ID 0xe4
+#define PONG_CU 0xc0ca
+struct senseid {
+ /* common part */
+ uint8_t reserved; /* always 0x'FF' */
+ uint16_t cu_type; /* control unit type */
+ uint8_t cu_model; /* control unit model */
+ uint16_t dev_type; /* device type */
+ uint8_t dev_model; /* device model */
+ uint8_t unused; /* padding byte */
+ uint8_t padding[256 - 10]; /* Extra padding for CCW */
+} __attribute__ ((aligned(4))) __attribute__ ((packed));
+
/* CSS low level access functions */
static inline int ssch(unsigned long schid, struct orb *addr)
@@ -254,4 +267,11 @@ static inline struct ccw *dump_ccw(struct ccw *cp)
return NULL;
}
#endif /* DEBUG_CSS */
+
+#define SID_ONE 0x00010000
+
+/* Library functions */
+int enable_subchannel(unsigned int sid);
+int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw);
+
#endif
diff --git a/lib/s390x/css_lib.c b/lib/s390x/css_lib.c
new file mode 100644
index 0000000..15d767a
--- /dev/null
+++ b/lib/s390x/css_lib.c
@@ -0,0 +1,55 @@
+/*
+ * Channel subsystem library functions
+ *
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Authors:
+ * Pierre Morel <pmorel@linux.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2.
+ */
+#include <stdint.h>
+#include <stddef.h>
+#include <css.h>
+
+int enable_subchannel(unsigned int sid)
+{
+ struct schib schib;
+ struct pmcw *pmcw = &schib.pmcw;
+ int try_count = 5;
+ int cc;
+
+ if (!(sid & SID_ONE))
+ return -1;
+
+ cc = stsch(sid, &schib);
+ if (cc)
+ return -cc;
+
+ do {
+ pmcw->flags |= PMCW_ENABLE;
+
+ cc = msch(sid, &schib);
+ if (cc)
+ return -cc;
+
+ cc = stsch(sid, &schib);
+ if (cc)
+ return -cc;
+
+ } while (!(pmcw->flags & PMCW_ENABLE) && --try_count);
+
+ return try_count;
+}
+
+int start_ccw1_chain(unsigned int sid, struct ccw1 *ccw)
+{
+ struct orb orb;
+
+ orb.intparm = sid;
+ orb.ctrl = ORB_F_INIT_IRQ|ORB_F_FORMAT|ORB_F_LPM_DFLT;
+ orb.cpa = (unsigned int) (unsigned long)ccw;
+
+ return ssch(sid, &orb);
+}
diff --git a/s390x/Makefile b/s390x/Makefile
index baebf18..166cb5c 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -53,6 +53,7 @@ cflatobjs += lib/s390x/interrupt.o
cflatobjs += lib/s390x/mmu.o
cflatobjs += lib/s390x/smp.o
cflatobjs += lib/s390x/css_dump.o
+cflatobjs += lib/s390x/css_lib.o
OBJDIRS += lib/s390x
diff --git a/s390x/css.c b/s390x/css.c
index aeee951..b9805a9 100644
--- a/s390x/css.c
+++ b/s390x/css.c
@@ -22,9 +22,34 @@
#include <asm/time.h>
#define SID_ONE 0x00010000
+#define PSW_PRG_MASK (PSW_MASK_IO | PSW_MASK_EA | PSW_MASK_BA)
+
+#define PONG_CU_TYPE 0xc0ca
+
+struct lowcore *lowcore = (void *)0x0;
static struct schib schib;
static int test_device_sid;
+#define NUM_CCW 100
+static struct ccw1 ccw[NUM_CCW];
+static struct irb irb;
+static struct senseid senseid;
+
+static void set_io_irq_subclass_mask(uint64_t const new_mask)
+{
+ asm volatile (
+ "lctlg %%c6, %%c6, %[source]\n"
+ : /* No outputs */
+ : [source] "R" (new_mask));
+}
+
+static void set_system_mask(uint8_t new_mask)
+{
+ asm volatile (
+ "ssm %[source]\n"
+ : /* No outputs */
+ : [source] "R" (new_mask));
+}
static void test_enumerate(void)
{
@@ -115,12 +140,139 @@ static void test_enable(void)
report(1, "Tested");
}
+static void enable_io_irq(void)
+{
+ /* Let's enable all ISCs for I/O interrupt */
+ set_io_irq_subclass_mask(0x00000000ff000000);
+ set_system_mask(PSW_PRG_MASK >> 56);
+}
+
+static void irq_io(void)
+{
+ int ret = 0;
+ char *flags;
+ int sid;
+
+ report_prefix_push("Interrupt");
+ /* Lowlevel set the SID as interrupt parameter. */
+ if (lowcore->io_int_param != test_device_sid) {
+ report(0, "Bad io_int_param: %x expected %x", lowcore->io_int_param, test_device_sid);
+ report_prefix_pop();
+ return;
+ }
+ report_prefix_pop();
+
+ report_prefix_push("tsch");
+ sid = lowcore->subsys_id_word;
+ ret = tsch(sid, &irb);
+ switch (ret) {
+ case 1:
+ dump_irb(&irb);
+ flags = dump_scsw_flags(irb.scsw.ctrl);
+ report(0, "I/O interrupt, but sch not status pending: %s", flags);
+ goto pop;
+ case 2:
+ report(0, "TSCH returns unexpected CC 2");
+ goto pop;
+ case 3:
+ report(0, "Subchannel %08x not operational", sid);
+ goto pop;
+ case 0:
+ /* Stay humble on success */
+ break;
+ }
+pop:
+ report_prefix_pop();
+}
+
+static int start_subchannel(int code, void *data, int count)
+{
+ int ret;
+
+ report_prefix_push("start_senseid");
+ /* Build the CCW chain with a single CCW */
+ ccw[0].code = code;
+ ccw[0].flags = 0; /* No flags need to be set */
+ ccw[0].count = count;
+ ccw[0].data_address = (int)(unsigned long)data;
+
+ ret = start_ccw1_chain(test_device_sid, ccw);
+ if (ret) {
+ report(0, "start_ccw_chain failed ret=%d", ret);
+ report_prefix_pop();
+ return 0;
+ }
+ report_prefix_pop();
+ return 1;
+}
+
+/*
+ * test_sense
+ * Pre-requisits:
+ * - We need the QEMU PONG device as the first recognized
+ * device by the enumeration.
+ * - ./s390x-run s390x/css.elf -device ccw-pong,cu_type=0xc0ca
+ */
+static void test_sense(void)
+{
+ int ret;
+
+ if (!test_device_sid) {
+ report_skip("No device");
+ return;
+ }
+
+ ret = enable_subchannel(test_device_sid);
+ if (ret < 0) {
+ report(0, "Could not enable the subchannel: %08x", test_device_sid);
+ return;
+ }
+
+ ret = register_io_int_func(irq_io);
+ if (ret) {
+ report(0, "Could not register IRQ handler");
+ goto unreg_cb;
+ }
+
+ enable_io_irq();
+ lowcore->io_int_param = 0;
+
+ ret = start_subchannel(CCW_CMD_SENSE_ID, &senseid, sizeof(senseid));
+ if (!ret) {
+ report(0, "start_senseid failed");
+ goto unreg_cb;
+ }
+
+ /* 100ms should be enough for the interruption to fire */
+ delay(100);
+ if (lowcore->io_int_param != test_device_sid) {
+ report(0, "No interrupts. io_int_param: expect 0x%08x, got 0x%08x",
+ test_device_sid, lowcore->io_int_param);
+ goto unreg_cb;
+ }
+
+ report_info("reserved %02x cu_type %04x cu_model %02x dev_type %04x dev_model %02x\n",
+ senseid.reserved, senseid.cu_type, senseid.cu_model,
+ senseid.dev_type, senseid.dev_model);
+
+ if (senseid.cu_type == PONG_CU)
+ report(1, "cu_type: expect 0x%04x got 0x%04x",
+ PONG_CU_TYPE, senseid.cu_type);
+ else
+ report(0, "cu_type: expect 0x%04x got 0x%04x",
+ PONG_CU_TYPE, senseid.cu_type);
+
+unreg_cb:
+ unregister_io_int_func(irq_io);
+}
+
static struct {
const char *name;
void (*func)(void);
} tests[] = {
{ "enumerate (stsch)", test_enumerate },
{ "enable (msch)", test_enable },
+ { "sense (ssch/tsch)", test_sense },
{ NULL, NULL }
};
--
2.17.0
^ permalink raw reply related
* [kvm-unit-tests PATCH v5 06/10] s390x: Library resources for CSS tests
From: Pierre Morel @ 2020-02-20 12:00 UTC (permalink / raw)
To: kvm; +Cc: linux-s390, frankja, david, thuth, cohuck
In-Reply-To: <1582200043-21760-1-git-send-email-pmorel@linux.ibm.com>
These are the include and library utilities for the css tests patch
series.
Debug function can be activated by defining DEBUG_CSS before the
inclusion of the css.h header file.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
lib/s390x/css.h | 256 +++++++++++++++++++++++++++++++++++++++++++
lib/s390x/css_dump.c | 157 ++++++++++++++++++++++++++
2 files changed, 413 insertions(+)
create mode 100644 lib/s390x/css.h
create mode 100644 lib/s390x/css_dump.c
diff --git a/lib/s390x/css.h b/lib/s390x/css.h
new file mode 100644
index 0000000..8144a21
--- /dev/null
+++ b/lib/s390x/css.h
@@ -0,0 +1,256 @@
+/*
+ * CSS definitions
+ *
+ * Copyright IBM, Corp. 2019
+ * Author: Pierre Morel <pmorel@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef CSS_H
+#define CSS_H
+
+#define CCW_F_CD 0x80
+#define CCW_F_CC 0x40
+#define CCW_F_SLI 0x20
+#define CCW_F_SKP 0x10
+#define CCW_F_PCI 0x08
+#define CCW_F_IDA 0x04
+#define CCW_F_S 0x02
+#define CCW_F_MIDA 0x01
+
+#define CCW_C_NOP 0x03
+#define CCW_C_TIC 0x08
+
+struct ccw1 {
+ unsigned char code;
+ unsigned char flags;
+ unsigned short count;
+ uint32_t data_address;
+} __attribute__ ((aligned(4)));
+
+#define ORB_M_KEY 0xf0000000
+#define ORB_F_SUSPEND 0x08000000
+#define ORB_F_STREAMING 0x04000000
+#define ORB_F_MODIFCTRL 0x02000000
+#define ORB_F_SYNC 0x01000000
+#define ORB_F_FORMAT 0x00800000
+#define ORB_F_PREFETCH 0x00400000
+#define ORB_F_INIT_IRQ 0x00200000
+#define ORB_F_ADDRLIMIT 0x00100000
+#define ORB_F_SUSP_IRQ 0x00080000
+#define ORB_F_TRANSPORT 0x00040000
+#define ORB_F_IDAW2 0x00020000
+#define ORB_F_IDAW_2K 0x00010000
+#define ORB_M_LPM 0x0000ff00
+#define ORB_F_LPM_DFLT 0x00008000
+#define ORB_F_ILSM 0x00000080
+#define ORB_F_CCW_IND 0x00000040
+#define ORB_F_ORB_EXT 0x00000001
+
+struct orb {
+ uint32_t intparm;
+ uint32_t ctrl;
+ uint32_t cpa;
+ uint32_t prio;
+ uint32_t reserved[4];
+} __attribute__ ((aligned(4)));
+
+struct scsw {
+ uint32_t ctrl;
+ uint32_t ccw_addr;
+ uint8_t dev_stat;
+ uint8_t sch_stat;
+ uint16_t count;
+};
+
+struct pmcw {
+ uint32_t intparm;
+#define PMCW_DNV 0x0001
+#define PMCW_ENABLE 0x0080
+ uint16_t flags;
+ uint16_t devnum;
+ uint8_t lpm;
+ uint8_t pnom;
+ uint8_t lpum;
+ uint8_t pim;
+ uint16_t mbi;
+ uint8_t pom;
+ uint8_t pam;
+ uint8_t chpid[8];
+ uint32_t flags2;
+};
+
+struct schib {
+ struct pmcw pmcw;
+ struct scsw scsw;
+ uint8_t md[12];
+} __attribute__ ((aligned(4)));
+
+struct irb {
+ struct scsw scsw;
+ uint32_t esw[5];
+ uint32_t ecw[8];
+ uint32_t emw[8];
+} __attribute__ ((aligned(4)));
+
+/* CSS low level access functions */
+
+static inline int ssch(unsigned long schid, struct orb *addr)
+{
+ register long long reg1 asm("1") = schid;
+ int cc;
+
+ asm volatile(
+ " ssch 0(%2)\n"
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (cc)
+ : "d" (reg1), "a" (addr), "m" (*addr)
+ : "cc", "memory");
+ return cc;
+}
+
+static inline int stsch(unsigned long schid, struct schib *addr)
+{
+ register unsigned long reg1 asm ("1") = schid;
+ int cc;
+
+ asm volatile(
+ " stsch 0(%3)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
+ return cc;
+}
+
+static inline int msch(unsigned long schid, struct schib *addr)
+{
+ register unsigned long reg1 asm ("1") = schid;
+ int cc;
+
+ asm volatile(
+ " msch 0(%3)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
+ return cc;
+}
+
+static inline int tsch(unsigned long schid, struct irb *addr)
+{
+ register unsigned long reg1 asm ("1") = schid;
+ int cc;
+
+ asm volatile(
+ " tsch 0(%3)\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc), "=m" (*addr)
+ : "d" (reg1), "a" (addr)
+ : "cc");
+ return cc;
+}
+
+static inline int hsch(unsigned long schid)
+{
+ register unsigned long reg1 asm("1") = schid;
+ int cc;
+
+ asm volatile(
+ " hsch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc)
+ : "d" (reg1)
+ : "cc");
+ return cc;
+}
+
+static inline int xsch(unsigned long schid)
+{
+ register unsigned long reg1 asm("1") = schid;
+ int cc;
+
+ asm volatile(
+ " xsch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc)
+ : "d" (reg1)
+ : "cc");
+ return cc;
+}
+
+static inline int csch(unsigned long schid)
+{
+ register unsigned long reg1 asm("1") = schid;
+ int cc;
+
+ asm volatile(
+ " csch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc)
+ : "d" (reg1)
+ : "cc");
+ return cc;
+}
+
+static inline int rsch(unsigned long schid)
+{
+ register unsigned long reg1 asm("1") = schid;
+ int cc;
+
+ asm volatile(
+ " rsch\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc)
+ : "d" (reg1)
+ : "cc");
+ return cc;
+}
+
+static inline int rchp(unsigned long chpid)
+{
+ register unsigned long reg1 asm("1") = chpid;
+ int cc;
+
+ asm volatile(
+ " rchp\n"
+ " ipm %0\n"
+ " srl %0,28"
+ : "=d" (cc)
+ : "d" (reg1)
+ : "cc");
+ return cc;
+}
+
+/* Debug functions */
+char *dump_pmcw_flags(uint16_t f);
+char *dump_scsw_flags(uint32_t f);
+
+#ifdef DEBUG_CSS
+void dump_scsw(struct scsw *);
+void dump_irb(struct irb *irbp);
+void dump_schib(struct schib *sch);
+struct ccw *dump_ccw(struct ccw *cp);
+#else
+static inline void dump_scsw(struct scsw *scsw) {}
+static inline void dump_irb(struct irb *irbp) {}
+static inline void dump_pmcw(struct pmcw *p) {}
+static inline void dump_schib(struct schib *sch) {}
+static inline void dump_orb(struct orb *op) {}
+static inline struct ccw *dump_ccw(struct ccw *cp)
+{
+ return NULL;
+}
+#endif /* DEBUG_CSS */
+#endif
diff --git a/lib/s390x/css_dump.c b/lib/s390x/css_dump.c
new file mode 100644
index 0000000..e34c391
--- /dev/null
+++ b/lib/s390x/css_dump.c
@@ -0,0 +1,157 @@
+/*
+ * Channel subsystem structures dumping
+ *
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Authors:
+ * Pierre Morel <pmorel@linux.ibm.com>
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2.
+ *
+ * Description:
+ * Provides the dumping functions for various structures used by subchannels:
+ * - ORB : Operation request block, describes the I/O operation and points to
+ * a CCW chain
+ * - CCW : Channel Command Word, describes the data and flow control
+ * - IRB : Interuption response Block, describes the result of an operation
+ * holds a SCSW and model-dependent data.
+ * - SCHIB: SubCHannel Information Block composed of:
+ * - SCSW: SubChannel Status Word, status of the channel.
+ * - PMCW: Path Management Control Word
+ * You need the QEMU ccw-pong device in QEMU to answer the I/O transfers.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#undef DEBUG_CSS
+#include <css.h>
+
+/*
+ * Try to have a more human representation of the SCSW flags:
+ * each letter in the two strings represent the first
+ * letter of the associated bit in the flag fields.
+ */
+static const char *scsw_str = "kkkkslccfpixuzen";
+static const char *scsw_str2 = "1SHCrshcsdsAIPSs";
+static char scsw_line[64] = {};
+
+char *dump_scsw_flags(uint32_t f)
+{
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ if ((f << i) & 0x80000000)
+ scsw_line[i] = scsw_str[i];
+ else
+ scsw_line[i] = '_';
+ }
+ scsw_line[i] = ' ';
+ for (; i < 32; i++) {
+ if ((f << i) & 0x80000000)
+ scsw_line[i + 1] = scsw_str2[i - 16];
+ else
+ scsw_line[i + 1] = '_';
+ }
+ return scsw_line;
+}
+
+/*
+ * Try o have a more human representation of the PMCW flags
+ * each letter in the two strings he under represent the first
+ * letter of the associated bit in the flag.
+ */
+static const char *pmcw_str = "11iii111ellmmdtv";
+static char pcmw_line[32] = {};
+char *dump_pmcw_flags(uint16_t f)
+{
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ if ((f << i) & 0x8000)
+ pcmw_line[i] = pmcw_str[i];
+ else
+ pcmw_line[i] = '_';
+ }
+ return pcmw_line;
+}
+
+#ifdef DEBUG_CSS
+void dump_scsw(struct scsw *s)
+{
+ dump_scsw_flags(s->ctrl);
+ printf("scsw->flags: %s\n", line);
+ printf("scsw->addr : %08x\n", s->addr);
+ printf("scsw->devs : %02x\n", s->devs);
+ printf("scsw->schs : %02x\n", s->schs);
+ printf("scsw->count: %04x\n", s->count);
+}
+
+void dump_irb(struct irb *irbp)
+{
+ int i;
+ uint32_t *p = (uint32_t *)irbp;
+
+ dump_scsw(&irbp->scsw);
+ for (i = 0; i < sizeof(*irbp)/sizeof(*p); i++, p++)
+ printf("irb[%02x] : %08x\n", i, *p);
+}
+
+void dump_pmcw(struct pmcw *p)
+{
+ int i;
+
+ printf("pmcw->intparm : %08x\n", p->intparm);
+ printf("pmcw->flags : %04x\n", p->flags);
+ dump_pmcw_flags(p->flags);
+ printf("pmcw->devnum : %04x\n", p->devnum);
+ printf("pmcw->lpm : %02x\n", p->lpm);
+ printf("pmcw->pnom : %02x\n", p->pnom);
+ printf("pmcw->lpum : %02x\n", p->lpum);
+ printf("pmcw->pim : %02x\n", p->pim);
+ printf("pmcw->mbi : %04x\n", p->mbi);
+ printf("pmcw->pom : %02x\n", p->pom);
+ printf("pmcw->pam : %02x\n", p->pam);
+ printf("pmcw->mbi : %04x\n", p->mbi);
+ for (i = 0; i < 8; i++)
+ printf("pmcw->chpid[%d]: %02x\n", i, p->chpid[i]);
+ printf("pmcw->flags2 : %08x\n", p->flags2);
+}
+
+void dump_schib(struct schib *sch)
+{
+ struct pmcw *p = &sch->pmcw;
+ struct scsw *s = &sch->scsw;
+
+ printf("--SCHIB--\n");
+ dump_pmcw(p);
+ dump_scsw(s);
+}
+
+struct ccw *dump_ccw(struct ccw *cp)
+{
+ printf("CCW: code: %02x flags: %02x count: %04x data: %08x\n", cp->code,
+ cp->flags, cp->count, cp->data);
+
+ if (cp->code == CCW_C_TIC)
+ return (struct ccw *)(long)cp->data;
+
+ return (cp->flags & CCW_F_CC) ? cp + 1 : NULL;
+}
+
+void dump_orb(struct orb *op)
+{
+ struct ccw *cp;
+
+ printf("ORB: intparm : %08x\n", op->intparm);
+ printf("ORB: ctrl : %08x\n", op->ctrl);
+ printf("ORB: prio : %08x\n", op->prio);
+ cp = (struct ccw *)(long) (op->cpa);
+ while (cp)
+ cp = dump_ccw(cp);
+}
+
+#endif
--
2.17.0
^ permalink raw reply related
* [PATCH v3 0/1] s390x: css: pong, channel subsystem test device
From: Pierre Morel @ 2020-02-20 11:59 UTC (permalink / raw)
To: qemu-s390x; +Cc: thuth, frankja, david, cohuck, qemu-devel, pasic
This patch series presents a device to test the channel subsystem.
Currently it only does the following:
- answer to WRITE requests by incrementing an integer stored as
string in the data of a PONG_WRITE CCW command.
- send back the same buffer, with the incremented integer when
receiving a PONG_READ CCW command.
- defines a Control Unit property.
Pierre Morel (1):
s390x: css: pong, channel subsystem test device
default-configs/s390x-softmmu.mak | 1 +
hw/s390x/Kconfig | 3 +
hw/s390x/Makefile.objs | 1 +
hw/s390x/ccw-pong.c | 140 ++++++++++++++++++++++++++++++
include/hw/s390x/pong.h | 54 ++++++++++++
5 files changed, 199 insertions(+)
create mode 100644 hw/s390x/ccw-pong.c
create mode 100644 include/hw/s390x/pong.h
--
2.17.0
Changelog:
v2 to v3:
- use device_class_set_props() instead to access
the properties directly
v1 to v2:
- use ccw_dstream_xxx_buf (Connie)
- adding a cu_type property
- testing the ccw.count
- conditional compiling for TEST_DEVICES (Connie, Thomas)
- suppress the device categorie (Connie ?)
- adding write callback and some funny protocol
^ permalink raw reply
* [PATCH v3 1/1] s390x: css: pong, channel subsystem test device
From: Pierre Morel @ 2020-02-20 11:59 UTC (permalink / raw)
To: qemu-s390x; +Cc: thuth, frankja, david, cohuck, qemu-devel, pasic
In-Reply-To: <1582199965-21584-1-git-send-email-pmorel@linux.ibm.com>
This is a test device for channel subsystem.
Most of the CSS instructions are handled by the common code.
The PONG_READ and PONG_WRITE CCW commands allow to test the
SSCH instruction with both read and write commands.
It is also possible to define the Control Unit type
with the cu_type property.
Currently only the kvm-unit-test css test uses the PONG device.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
default-configs/s390x-softmmu.mak | 1 +
hw/s390x/Kconfig | 3 +
hw/s390x/Makefile.objs | 1 +
hw/s390x/ccw-pong.c | 140 ++++++++++++++++++++++++++++++
include/hw/s390x/pong.h | 54 ++++++++++++
5 files changed, 199 insertions(+)
create mode 100644 hw/s390x/ccw-pong.c
create mode 100644 include/hw/s390x/pong.h
diff --git a/default-configs/s390x-softmmu.mak b/default-configs/s390x-softmmu.mak
index f2287a133f..72711912cd 100644
--- a/default-configs/s390x-softmmu.mak
+++ b/default-configs/s390x-softmmu.mak
@@ -7,6 +7,7 @@
#CONFIG_VFIO_CCW=n
#CONFIG_VIRTIO_PCI=n
#CONFIG_WDT_DIAG288=n
+#CONFIG_CCW_TESTDEV=n
# Boards:
#
diff --git a/hw/s390x/Kconfig b/hw/s390x/Kconfig
index 5e7d8a2bae..041ede333e 100644
--- a/hw/s390x/Kconfig
+++ b/hw/s390x/Kconfig
@@ -10,3 +10,6 @@ config S390_CCW_VIRTIO
select SCLPCONSOLE
select VIRTIO_CCW
select MSI_NONBROKEN
+
+config CCW_TESTDEV
+ default y if TEST_DEVICES
diff --git a/hw/s390x/Makefile.objs b/hw/s390x/Makefile.objs
index e02ed80b68..e74d0efd9d 100644
--- a/hw/s390x/Makefile.objs
+++ b/hw/s390x/Makefile.objs
@@ -34,3 +34,4 @@ obj-$(CONFIG_KVM) += s390-stattrib-kvm.o
obj-y += s390-ccw.o
obj-y += ap-device.o
obj-y += ap-bridge.o
+obj-y += ccw-pong.o
diff --git a/hw/s390x/ccw-pong.c b/hw/s390x/ccw-pong.c
new file mode 100644
index 0000000000..28177eddae
--- /dev/null
+++ b/hw/s390x/ccw-pong.c
@@ -0,0 +1,140 @@
+/*
+ * CCW PING-PONG
+ *
+ * Copyright 2019 IBM Corp.
+ * Author(s): Pierre Morel <pmorel@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "cpu.h"
+#include "exec/address-spaces.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/css-bridge.h"
+#include "hw/qdev-properties.h"
+#include "hw/s390x/pong.h"
+
+#define PONG_BUF_SIZE 0x1000
+static char buf[PONG_BUF_SIZE];
+
+static int pong_ccw_cb(SubchDev *sch, CCW1 ccw)
+{
+ int rc = 0;
+ static int value;
+ int len;
+
+ len = (ccw.count > PONG_BUF_SIZE) ? PONG_BUF_SIZE : ccw.count;
+ switch (ccw.cmd_code) {
+ case PONG_WRITE:
+ rc = ccw_dstream_read_buf(&sch->cds, buf, len);
+ value = atol(buf);
+ break;
+ case PONG_READ:
+ sprintf(buf, "%08x", value + 1);
+ rc = ccw_dstream_write_buf(&sch->cds, buf, len);
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ sch->curr_status.scsw.count = ccw_dstream_residual_count(&sch->cds);
+
+ if (rc == -EIO) {
+ /* I/O error, specific devices generate specific conditions */
+ SCHIB *schib = &sch->curr_status;
+
+ sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
+ sch->sense_data[0] = 0x40; /* intervention-req */
+ schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
+ schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
+ schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+ SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+ }
+ return rc;
+}
+
+static void pong_ccw_realize(DeviceState *ds, Error **errp)
+{
+ uint16_t chpid;
+ CcwPONGDevice *dev = CCW_PONG(ds);
+ CcwDevice *cdev = CCW_DEVICE(ds);
+ CCWDeviceClass *cdk = CCW_DEVICE_GET_CLASS(cdev);
+ SubchDev *sch;
+ Error *err = NULL;
+
+ sch = css_create_sch(cdev->devno, errp);
+ if (!sch) {
+ return;
+ }
+
+ sch->driver_data = dev;
+ cdev->sch = sch;
+ chpid = css_find_free_chpid(sch->cssid);
+
+ if (chpid > MAX_CHPID) {
+ error_setg(&err, "No available chpid to use.");
+ goto out_err;
+ }
+
+ sch->id.reserved = 0xff;
+ sch->id.cu_type = dev->cu_type;
+ sch->id.cu_model = dev->cu_model;
+ sch->id.dev_type = dev->dev_type;
+ sch->id.dev_model = dev->dev_model;
+ css_sch_build_virtual_schib(sch, (uint8_t)chpid, CCW_PONG_CHPID_TYPE);
+ sch->do_subchannel_work = do_subchannel_work_virtual;
+ sch->ccw_cb = pong_ccw_cb;
+
+ cdk->realize(cdev, &err);
+ if (err) {
+ goto out_err;
+ }
+
+ css_reset_sch(sch);
+ return;
+
+out_err:
+ error_propagate(errp, err);
+ css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
+ cdev->sch = NULL;
+ g_free(sch);
+}
+
+static Property pong_ccw_properties[] = {
+ DEFINE_PROP_UINT16("cu_type", CcwPONGDevice, cu_type, CCW_PONG_CU_TYPE),
+ DEFINE_PROP_UINT8("cu_model", CcwPONGDevice, cu_model, CCW_PONG_CU_MODEL),
+ DEFINE_PROP_UINT16("dev_type", CcwPONGDevice, dev_type, CCW_PONG_DEV_TYPE),
+ DEFINE_PROP_UINT8("dev_model", CcwPONGDevice, dev_model, CCW_PONG_DEV_MODEL),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pong_ccw_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ device_class_set_props(dc, pong_ccw_properties);
+ dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
+ dc->realize = pong_ccw_realize;
+ dc->hotpluggable = false;
+}
+
+static const TypeInfo pong_ccw_info = {
+ .name = TYPE_CCW_PONG,
+ .parent = TYPE_CCW_DEVICE,
+ .instance_size = sizeof(CcwPONGDevice),
+ .class_init = pong_ccw_class_init,
+ .class_size = sizeof(CcwPONGClass),
+};
+
+static void pong_ccw_register(void)
+{
+ type_register_static(&pong_ccw_info);
+}
+
+type_init(pong_ccw_register)
diff --git a/include/hw/s390x/pong.h b/include/hw/s390x/pong.h
new file mode 100644
index 0000000000..1e60aef24e
--- /dev/null
+++ b/include/hw/s390x/pong.h
@@ -0,0 +1,54 @@
+/*
+ * ccw-attached PONG definitions
+ *
+ * Copyright 2019 IBM Corp.
+ * Author(s): Pierre Morel <pmorel@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_S390X_PONG_CCW_H
+#define HW_S390X_PONG_CCW_H
+
+#include "hw/sysbus.h"
+#include "hw/s390x/css.h"
+#include "hw/s390x/ccw-device.h"
+
+#define CCW_PONG_CU_TYPE 0xc0ca
+#define CCW_PONG_CU_MODEL 0xa7
+#define CCW_PONG_DEV_TYPE 0xcafe
+#define CCW_PONG_DEV_MODEL 0xe5
+#define CCW_PONG_CHPID_TYPE 0xd0
+
+#define TYPE_CCW_PONG "ccw-pong"
+
+/* Local Channel Commands */
+#define PONG_WRITE 0x21 /* Write */
+#define PONG_READ 0x22 /* Read buffer */
+
+#define CCW_PONG(obj) \
+ OBJECT_CHECK(CcwPONGDevice, (obj), TYPE_CCW_PONG)
+#define CCW_PONG_CLASS(klass) \
+ OBJECT_CLASS_CHECK(CcwPONGClass, (klass), TYPE_CCW_PONG)
+#define CCW_PONG_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(CcwPONGClass, (obj), TYPE_CCW_PONG)
+
+typedef struct CcwPONGDevice {
+ CcwDevice parent_obj;
+ uint16_t cu_type;
+ uint8_t cu_model;
+ uint16_t dev_type;
+ uint8_t dev_model;
+} CcwPONGDevice;
+
+typedef struct CcwPONGClass {
+ CCWDeviceClass parent_class;
+
+ void (*init)(CcwPONGDevice *, Error **);
+ int (*read_payload)(CcwPONGDevice *);
+ int (*write_payload)(CcwPONGDevice *, uint8_t);
+} CcwPONGClass;
+
+#endif
--
2.17.0
^ permalink raw reply related
* [kvm-unit-tests PATCH v5 01/10] s390x: saving regs for interrupts
From: Pierre Morel @ 2020-02-20 12:00 UTC (permalink / raw)
To: kvm; +Cc: linux-s390, frankja, david, thuth, cohuck
In-Reply-To: <1582200043-21760-1-git-send-email-pmorel@linux.ibm.com>
If we use multiple source of interrupts, for example, using SCLP
console to print information while using I/O interrupts, we need
to have a re-entrant register saving interruption handling.
Instead of saving at a static memory address, let's save the base
registers and the floating point registers on the stack.
Note that we keep the static register saving to recover from the
RESET tests.
Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
---
s390x/cstart64.S | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/s390x/cstart64.S b/s390x/cstart64.S
index 9af6bb3..45da523 100644
--- a/s390x/cstart64.S
+++ b/s390x/cstart64.S
@@ -118,6 +118,25 @@ memsetxc:
lmg %r0, %r15, GEN_LC_SW_INT_GRS
.endm
+/* Save registers on the stack, so we can have stacked interrupts. */
+ .macro SAVE_IRQ_REGS
+ slgfi %r15, 15 * 8
+ stmg %r0, %r14, 0(%r15)
+ slgfi %r15, 16 * 8
+ .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ std \i, \i * 8(%r15)
+ .endr
+ .endm
+
+ .macro RESTORE_IRQ_REGS
+ .irp i, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ ld \i, \i * 8(%r15)
+ .endr
+ algfi %r15, 16 * 8
+ lmg %r0, %r14, 0(%r15)
+ algfi %r15, 15 * 8
+ .endm
+
.section .text
/*
* load_reset calling convention:
@@ -182,9 +201,9 @@ mcck_int:
lpswe GEN_LC_MCCK_OLD_PSW
io_int:
- SAVE_REGS
+ SAVE_IRQ_REGS
brasl %r14, handle_io_int
- RESTORE_REGS
+ RESTORE_IRQ_REGS
lpswe GEN_LC_IO_OLD_PSW
svc_int:
--
2.17.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
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.