LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 0/8] Implement EBPF on powerpc32
From: Andrii Nakryiko @ 2021-03-22 17:53 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Song Liu, Daniel Borkmann, john fastabend, Andrii Nakryiko,
	Alexei Starovoitov, naveen.n.rao, Networking, Paul Mackerras,
	sandipan, KP Singh, Yonghong Song, bpf, linuxppc-dev, Martin Lau,
	open list
In-Reply-To: <cover.1616430991.git.christophe.leroy@csgroup.eu>

On Mon, Mar 22, 2021 at 9:37 AM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
> This series implements extended BPF on powerpc32. For the implementation
> details, see the patch before the last.
>
> The following operations are not implemented:
>
>                 case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */
>                 case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */
>                 case BPF_STX | BPF_XADD | BPF_DW: /* *(u64 *)(dst + off) += src */
>
> The following operations are only implemented for power of two constants:
>
>                 case BPF_ALU64 | BPF_MOD | BPF_K: /* dst %= imm */
>                 case BPF_ALU64 | BPF_DIV | BPF_K: /* dst /= imm */
>
> Below are the results on a powerpc 885:
> - with the patch, with and without bpf_jit_enable
> - without the patch, with bpf_jit_enable (ie with CBPF)
>
> With the patch, with bpf_jit_enable = 1 :
>
> [   60.826529] test_bpf: Summary: 378 PASSED, 0 FAILED, [354/366 JIT'ed]
> [   60.832505] test_bpf: test_skb_segment: Summary: 2 PASSED, 0 FAILED
>
> With the patch, with bpf_jit_enable = 0 :
>
> [   75.186337] test_bpf: Summary: 378 PASSED, 0 FAILED, [0/366 JIT'ed]
> [   75.192325] test_bpf: test_skb_segment: Summary: 2 PASSED, 0 FAILED
>
> Without the patch, with bpf_jit_enable = 1 :
>
> [  186.112429] test_bpf: Summary: 371 PASSED, 7 FAILED, [119/366 JIT'ed]
>
> Couldn't run test_progs because it doesn't build (clang 11 crashes during the build).

Can you please try checking out the latest clang from sources and use
that one instead?

>
> Changes in v2:
> - Simplify 16 bits swap
> - Rework tailcall, use stack for tailcall counter
> - Fix handling of BPF_REG_FP:
>   - must be handler like any other register allthough only the lower 32 bits part is used as a pointer.
>   - r18 was TMP_REG, r17/r18 become de BPF_REG_FP
>   - r31 was BPF_REG_FP, it is now TMP_REG
> - removed bpf_jit32.h
> - Reorder register allocation dynamically to use the volatile registers as much as possible when not doing function calls (last patch - new)
>
> Christophe Leroy (8):
>   powerpc/bpf: Remove classical BPF support for PPC32
>   powerpc/bpf: Change register numbering for bpf_set/is_seen_register()
>   powerpc/bpf: Move common helpers into bpf_jit.h
>   powerpc/bpf: Move common functions into bpf_jit_comp.c
>   powerpc/bpf: Change values of SEEN_ flags
>   powerpc/asm: Add some opcodes in asm/ppc-opcode.h for PPC32 eBPF
>   powerpc/bpf: Implement extended BPF on PPC32
>   powerpc/bpf: Reallocate BPF registers to volatile registers when
>     possible on PPC32
>
>  Documentation/admin-guide/sysctl/net.rst |    2 +-
>  arch/powerpc/Kconfig                     |    3 +-
>  arch/powerpc/include/asm/ppc-opcode.h    |   12 +
>  arch/powerpc/net/Makefile                |    6 +-
>  arch/powerpc/net/bpf_jit.h               |   61 ++
>  arch/powerpc/net/bpf_jit32.h             |  139 ---
>  arch/powerpc/net/bpf_jit64.h             |   21 +-
>  arch/powerpc/net/bpf_jit_asm.S           |  226 -----
>  arch/powerpc/net/bpf_jit_comp.c          |  782 ++++-----------
>  arch/powerpc/net/bpf_jit_comp32.c        | 1095 ++++++++++++++++++++++
>  arch/powerpc/net/bpf_jit_comp64.c        |  295 +-----
>  11 files changed, 1372 insertions(+), 1270 deletions(-)
>  delete mode 100644 arch/powerpc/net/bpf_jit32.h
>  delete mode 100644 arch/powerpc/net/bpf_jit_asm.S
>  create mode 100644 arch/powerpc/net/bpf_jit_comp32.c
>
> --
> 2.25.0
>

^ permalink raw reply

* Re: [PATCH next v1 2/3] printk: remove safe buffers
From: Petr Mladek @ 2021-03-22 18:02 UTC (permalink / raw)
  To: John Ogness
  Cc: Rafael Aquini, Alexey Kardashevskiy, Paul Mackerras, Tiezhu Yang,
	Peter Zijlstra, Yue Hu, Jordan Niethe, Kees Cook,
	Paul E. McKenney, Alistair Popple, Guilherme G. Piccoli,
	Nicholas Piggin, Steven Rostedt, Thomas Gleixner, kexec,
	linux-kernel, Sergey Senozhatsky, Eric Biederman, Andrew Morton,
	linuxppc-dev, Cédric Le Goater
In-Reply-To: <87k0pzmoao.fsf@jogness.linutronix.de>

On Mon 2021-03-22 12:16:15, John Ogness wrote:
> On 2021-03-21, Sergey Senozhatsky <senozhatsky@chromium.org> wrote:
> >> @@ -369,7 +70,10 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
> >>  	 * Use the main logbuf even in NMI. But avoid calling console
> >>  	 * drivers that might have their own locks.
> >>  	 */
> >> -	if ((this_cpu_read(printk_context) & PRINTK_NMI_DIRECT_CONTEXT_MASK)) {
> >> +	if (this_cpu_read(printk_context) &
> >> +	    (PRINTK_NMI_DIRECT_CONTEXT_MASK |
> >> +	     PRINTK_NMI_CONTEXT_MASK |
> >> +	     PRINTK_SAFE_CONTEXT_MASK)) {
> >
> > Do we need printk_nmi_direct_enter/exit() and
> > PRINTK_NMI_DIRECT_CONTEXT_MASK?  Seems like all printk_safe() paths
> > are now DIRECT - we store messages to the prb, but don't call console
> > drivers.
>
> I was planning on waiting until the kthreads are introduced, in which
> case printk_safe.c is completely removed.

You want to keep printk_safe() context because it prevents calling
consoles even in normal context. Namely, it prevents deadlock by
recursively taking, for example, sem->lock in console_lock() or
console_owner_lock in console_trylock_spinning(). Am I right?


> But I suppose I could switch
> the 1 printk_nmi_direct_enter() user to printk_nmi_enter() so that
> PRINTK_NMI_DIRECT_CONTEXT_MASK can be removed now. I would do this in a
> 4th patch of the series.

Yes, please unify the PRINTK_NMI_CONTEXT. One is enough.

I wonder if it would make sense to go even further at this stage.
There will still be 4 contexts that modify the printk behavior after
this patchset:

  + printk_count set by printk_enter()/exit()
      + prevents: infinite recursion
      + context: any context
      + action: skips entire printk at 3rd recursion level

  + prink_context set by printk_safe_enter()/exit()
      + prevents: dead lock caused by recursion into some
		console code in any context
      + context: any
      + action: skips console call at 1st recursion level

  + printk_context set by printk_nmi_enter()/exit()
      + prevents: dead lock caused by any console lock recursion
      + context: NMI
      + action: skips console calls at 0th recursion level

  + kdb_trap_printk
      + redirects printk() to kdb_printk() in kdb context


What is possible?

1. We could get rid of printk_nmi_enter()/exit() and
   PRINTK_NMI_CONTEXT completely already now. It is enough
   to check in_nmi() in printk_func().

   printk_nmi_enter() was added by the commit 42a0bb3f71383b457a7db362
   ("printk/nmi: generic solution for safe printk in NMI"). It was
   really needed to modify @printk_func pointer.

   We did not remove it later when printk_function became a real
   function. The idea was to track all printk contexts in a single
   variable. But we never added kdb context.

   It might make sense to remove it now. Peter Zijstra would be happy.
   There already were some churns with tracking printk_context in NMI.
   For example, see
   https://lore.kernel.org/r/20200219150744.428764577@infradead.org

   IMHO, it does not make sense to wait until the entire console-stuff
   rework is done in this case.


2. I thought about unifying printk_safe_enter()/exit() and
   printk_enter()/exit(). They both count recursion with
   IRQs disabled, have similar name. But they are used
   different way.

   But better might be to rename printk_safe_enter()/exit() to
   console_enter()/exit() or to printk_deferred_enter()/exit().
   It would make more clear what it does now. And it might help
   to better distinguish it from the new printk_enter()/exit().

   This patchset actually splits the original printk_safe()
   functionality into two:

       + printk_count prevents infinite recursion
       + printk_deferred_enter() deffers console handling.

   I am not sure if it is worth it. But it might help people (even me)
   when digging into the printk history. Different name will help to
   understand the functionality at the given time.


What do you think, please?

Best Regards,
Petr

^ permalink raw reply

* Re: [RFC PATCH 6/8] powerpc/mm/book3s64/hash: drop pre 2.06 tlbiel for clang
From: Nicholas Piggin @ 2021-03-22 18:11 UTC (permalink / raw)
  To: Christophe Leroy, Daniel Axtens, linuxppc-dev, llvmlinux
In-Reply-To: <7f7cafb5-e6c4-5015-5285-9f9ca25e52fb@csgroup.eu>

Excerpts from Christophe Leroy's message of March 23, 2021 2:49 am:
> 
> 
> Le 19/03/2021 à 03:01, Nicholas Piggin a écrit :
>> Excerpts from Daniel Axtens's message of February 25, 2021 1:10 pm:
>>> The llvm integrated assembler does not recognise the ISA 2.05 tlbiel
>>> version. Eventually do this more smartly.
>> 
>> The whole thing with TLBIE and TLBIEL in this file seems a bit too
>> clever. We should have PPC_TLBIE* macros for all of them.
> 
> I was expecting to drop PPC_* macros as much as possible taking into account the later binutils 
> support most of them (https://github.com/linuxppc/issues/issues/350). Was not expecting to go the 
> other direction.

The problem in this file is we generate 3 different tlbie and tlbiel
instructions with the same mnemonic corresponding to different ISA
versions.

This might actually be the one good place to use .machine to make sure 
the assembler generates the right thing. I'm not entirely sure it is
foolproof because some of the times the instruction variant is inferred
by the number of arguments it has yet arguments can be implicit. PPC_
define would be exactly explicit.

But if it can be made reasonably robust with .machine then I'd be okay
with that too.

Thanks,
Nick

^ permalink raw reply

* Re: [PATCH v3 17/41] KVM: PPC: Book3S HV P9: implement kvmppc_xive_pull_vcpu in C
From: Nicholas Piggin @ 2021-03-22 18:13 UTC (permalink / raw)
  To: Cédric Le Goater, kvm-ppc; +Cc: linuxppc-dev
In-Reply-To: <11823cfb-3d10-8f2f-4caf-9b38a010ed31@kaod.org>

Excerpts from Cédric Le Goater's message of March 23, 2021 2:19 am:
> On 3/5/21 4:06 PM, Nicholas Piggin wrote:
>> This is more symmetric with kvmppc_xive_push_vcpu. The extra test in
>> the asm will go away in a later change.
>> 
>> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> 
> Reviewed-by: Cédric Le Goater <clg@kaod.org>
>> diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c
>> index e7219b6f5f9a..52cdb9e2660a 100644
>> --- a/arch/powerpc/kvm/book3s_xive.c
>> +++ b/arch/powerpc/kvm/book3s_xive.c
>> @@ -127,6 +127,37 @@ void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu)
>>  }
>>  EXPORT_SYMBOL_GPL(kvmppc_xive_push_vcpu);
>>  
>> +/*
>> + * Pull a vcpu's context from the XIVE on guest exit.
>> + * This assumes we are in virtual mode (MMU on)
> 
> should we add an assert on is_rm() ? 

I thought the same thing at first, but I think it should be okay.
kvmppc_xive_push_cpu does not have an assert, and in the next
patch the push and pull get moved out to where it is much clearer
to see the MMU is on.

Thanks,
Nick

^ permalink raw reply

* Re: [PATCH v3 19/41] KVM: PPC: Book3S HV P9: Stop handling hcalls in real-mode in the P9 path
From: Nicholas Piggin @ 2021-03-22 18:22 UTC (permalink / raw)
  To: Alexey Kardashevskiy, Cédric Le Goater, kvm-ppc; +Cc: linuxppc-dev
In-Reply-To: <cc1660a7-e81e-b7b3-a841-35fb77fb571b@kaod.org>

Excerpts from Cédric Le Goater's message of March 23, 2021 2:01 am:
> On 3/22/21 2:15 PM, Nicholas Piggin wrote:
>> Excerpts from Alexey Kardashevskiy's message of March 22, 2021 5:30 pm:
>>>
>>>
>>> On 06/03/2021 02:06, Nicholas Piggin wrote:
>>>> In the interest of minimising the amount of code that is run in>>> "real-mode", don't handle hcalls in real mode in the P9 path.
>>>>
>>>> POWER8 and earlier are much more expensive to exit from HV real mode
>>>> and switch to host mode, because on those processors HV interrupts get
>>>> to the hypervisor with the MMU off, and the other threads in the core
>>>> need to be pulled out of the guest, and SLBs all need to be saved,
>>>> ERATs invalidated, and host SLB reloaded before the MMU is re-enabled
>>>> in host mode. Hash guests also require a lot of hcalls to run. The
>>>> XICS interrupt controller requires hcalls to run.
>>>>
>>>> By contrast, POWER9 has independent thread switching, and in radix mode
>>>> the hypervisor is already in a host virtual memory mode when the HV
>>>> interrupt is taken. Radix + xive guests don't need hcalls to handle
>>>> interrupts or manage translations.
> 
> Do we need to handle the host-is-a-P9-without-xive case ?

I'm not sure really. Is there an intention for OPAL to be able to 
provide a fallback layer in the worst case? Maybe microwatt grows
HV capability before XIVE?

> 
>>>> So it's much less important to handle hcalls in real mode in P9.
>>>
>>> So acde25726bc6034b (which added if(kvm_is_radix(vcpu->kvm))return 
>>> H_TOO_HARD) can be reverted, pretty much?
>> 
>> Yes. Although that calls attention to the fact I missed doing
>> a P9 h_random handler in this patch. I'll fix that, then I think
>> acde2572 could be reverted entirely.
>> 
>> [...]
>> 
>>>>   	} else {
>>>>   		kvmppc_xive_push_vcpu(vcpu);
>>>>   		trap = kvmhv_load_hv_regs_and_go(vcpu, time_limit, lpcr);
>>>> -		kvmppc_xive_pull_vcpu(vcpu);
>>>> +		/* H_CEDE has to be handled now, not later */
>>>> +		/* XICS hcalls must be handled before xive is pulled */
>>>> +		if (trap == BOOK3S_INTERRUPT_SYSCALL &&
>>>> +		    !(vcpu->arch.shregs.msr & MSR_PR)) {
>>>> +			unsigned long req = kvmppc_get_gpr(vcpu, 3);
>>>>   
>>>> +			if (req == H_CEDE) {
>>>> +				kvmppc_cede(vcpu);
>>>> +				kvmppc_xive_cede_vcpu(vcpu); /* may un-cede */
>>>> +				kvmppc_set_gpr(vcpu, 3, 0);
>>>> +				trap = 0;
>>>> +			}
>>>> +			if (req == H_EOI || req == H_CPPR ||
>>>
>>> else if (req == H_EOI ... ?
>> 
>> Hummm, sure.
> 
> you could integrate the H_CEDE in the switch statement below.

Below is in a different file just for the emulation calls.

>> 
>> [...]
>> 
>>>> +void kvmppc_xive_cede_vcpu(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	void __iomem *esc_vaddr = (void __iomem *)vcpu->arch.xive_esc_vaddr;
>>>> +
>>>> +	if (!esc_vaddr)
>>>> +		return;
>>>> +
>>>> +	/* we are using XIVE with single escalation */
>>>> +
>>>> +	if (vcpu->arch.xive_esc_on) {
>>>> +		/*
>>>> +		 * If we still have a pending escalation, abort the cede,
>>>> +		 * and we must set PQ to 10 rather than 00 so that we don't
>>>> +		 * potentially end up with two entries for the escalation
>>>> +		 * interrupt in the XIVE interrupt queue.  In that case
>>>> +		 * we also don't want to set xive_esc_on to 1 here in
>>>> +		 * case we race with xive_esc_irq().
>>>> +		 */
>>>> +		vcpu->arch.ceded = 0;
>>>> +		/*
>>>> +		 * The escalation interrupts are special as we don't EOI them.
>>>> +		 * There is no need to use the load-after-store ordering offset
>>>> +		 * to set PQ to 10 as we won't use StoreEOI.
>>>> +		 */
>>>> +		__raw_readq(esc_vaddr + XIVE_ESB_SET_PQ_10);
>>>> +	} else {
>>>> +		vcpu->arch.xive_esc_on = true;
>>>> +		mb();
>>>> +		__raw_readq(esc_vaddr + XIVE_ESB_SET_PQ_00);
>>>> +	}
>>>> +	mb();
>>>
>>>
>>> Uff. Thanks for cut-n-pasting the comments, helped a lot to match this c 
>>> to that asm!
>> 
>> Glad it helped.
>>>> +}
> 
> I had to do the PowerNV models in QEMU to start understanding that stuff ... 
> 
>>>> +EXPORT_SYMBOL_GPL(kvmppc_xive_cede_vcpu);
>>>> +
>>>>   /*
>>>>    * This is a simple trigger for a generic XIVE IRQ. This must
>>>>    * only be called for interrupts that support a trigger page
>>>> @@ -2106,6 +2140,32 @@ static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
>>>>   	return 0;
>>>>   }
>>>>   
>>>> +int kvmppc_xive_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
>>>> +{
>>>> +	struct kvmppc_vcore *vc = vcpu->arch.vcore;
>>>
>>>
>>> Can a XIVE enabled guest issue these hcalls? Don't we want if 
>>> (!kvmppc_xics_enabled(vcpu)) and
>>>   if (xics_on_xive()) here, as kvmppc_rm_h_xirr() have? Some of these 
>>> hcalls do write to XIVE registers but some seem to change 
>>> kvmppc_xive_vcpu. Thanks,
>> 
>> Yes I think you're right, good catch. I'm not completely sure about all 
>> the xive and xics modes but a guest certainly can make any kind of hcall 
>> it likes and we have to sanity check it.
> 
> Yes. 
> 
>> We want to take the hcall here (in replacement of the real mode hcalls)
>> with the same condition. So it would be:
>> 
>>         if (!kvmppc_xics_enabled(vcpu))
>>                 return H_TOO_HARD;
> 
> Yes.
> 
> This test covers the case in which a vCPU does XICS hcalls without QEMU 
> having connected the vCPU to a XICS ICP. The ICP is the KVM XICS device 
> on P8 or XICS-on-XIVE on P9. It catches QEMU errors when the interrupt 
> mode is negotiated, we don't want the OS to do XICS hcalls after having 
> negotiated the XIVE interrupt mode. 

Okay.

> It's different for the XIVE hcalls (when running under XICS) because they 
> are all handled in QEMU. 

XIVE guest hcalls running on XICS host?

>>         if (!xics_on_xive())
>> 		return H_TOO_HARD;
> 
> I understand that this code is only called on P9 and with translation on.

Yes.

> On P9, we could have xics_on_xive() == 0 if XIVE is disabled at compile 
> time or with "xive=off" at boot time. But guests should be supported. 
> I don't see a reason to restrict the support even if these scenarios 
> are rather unusual if not very rare.
> 
> on P10, it's the same but since we don't have the XICS emulation layer 
> in OPAL, the host will be pretty useless. We don't care.
> 
> Since we are trying to handle hcalls, this is L0 and it can not be called 
> for nested guests, which would be another case of xics_on_xive() == 0. 
> We don't care either.

Okay so no xics_on_xive() test. I'll change that.

Thanks,
Nick

^ permalink raw reply

* Re: [PATCH] powerpc/8xx: Fix a typo
From: Randy Dunlap @ 2021-03-22 18:43 UTC (permalink / raw)
  To: Bhaskar Chowdhury, mpe, benh, paulus, christophe.leroy, rppt,
	npiggin, akpm, linuxppc-dev, linux-kernel
In-Reply-To: <20210322120314.2085782-1-unixbhaskar@gmail.com>

On 3/22/21 5:03 AM, Bhaskar Chowdhury wrote:
> 
> s/poiners/pointers/
> 
> Signed-off-by: Bhaskar Chowdhury <unixbhaskar@gmail.com>

Acked-by: Randy Dunlap <rdunlap@infradead.org>


> ---
>  arch/powerpc/kernel/head_8xx.S | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
> index 46dff3f9c31f..8a85a984609a 100644
> --- a/arch/powerpc/kernel/head_8xx.S
> +++ b/arch/powerpc/kernel/head_8xx.S
> @@ -819,7 +819,7 @@ EXPORT_SYMBOL(empty_zero_page)
>  swapper_pg_dir:
>  	.space	PGD_TABLE_SIZE
> 
> -/* Room for two PTE table poiners, usually the kernel and current user
> +/* Room for two PTE table pointers, usually the kernel and current user
>   * pointer to their respective root page table (pgdir).
>   */
>  	.globl	abatron_pteptrs
> --


-- 
~Randy


^ permalink raw reply

* Re: [PATCH] powerpc/asm: Fix a typo
From: Randy Dunlap @ 2021-03-22 18:45 UTC (permalink / raw)
  To: Bhaskar Chowdhury, mpe, benh, paulus, linuxppc-dev, linux-kernel
In-Reply-To: <20210322113254.2081445-1-unixbhaskar@gmail.com>

On 3/22/21 4:32 AM, Bhaskar Chowdhury wrote:
> 
> s/poiner/pointer/
> 
> Signed-off-by: Bhaskar Chowdhury <unixbhaskar@gmail.com>

Acked-by: Randy Dunlap <rdunlap@infradead.org>

However, it would be a GOOD THING to collect multiple similar
patches that are in e.g. arch/powerpc/ and send them as one patch
instead of many little patches.


> ---
>  arch/powerpc/include/asm/cpm2.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/include/asm/cpm2.h b/arch/powerpc/include/asm/cpm2.h
> index 2211b934ecb4..bda45788cfcc 100644
> --- a/arch/powerpc/include/asm/cpm2.h
> +++ b/arch/powerpc/include/asm/cpm2.h
> @@ -594,7 +594,7 @@ typedef struct fcc_enet {
>  	uint	fen_p256c;	/* Total packets 256 < bytes <= 511 */
>  	uint	fen_p512c;	/* Total packets 512 < bytes <= 1023 */
>  	uint	fen_p1024c;	/* Total packets 1024 < bytes <= 1518 */
> -	uint	fen_cambuf;	/* Internal CAM buffer poiner */
> +	uint	fen_cambuf;	/* Internal CAM buffer pointer */
>  	ushort	fen_rfthr;	/* Received frames threshold */
>  	ushort	fen_rfcnt;	/* Received frames count */
>  } fcc_enet_t;
> --


-- 
~Randy


^ permalink raw reply

* Re: [PATCH] docs: powerpc: Fix a typo
From: Randy Dunlap @ 2021-03-22 18:49 UTC (permalink / raw)
  To: Bhaskar Chowdhury, mpe, benh, paulus, corbet, linuxppc-dev,
	linux-doc, linux-kernel
In-Reply-To: <20210322062237.2971314-1-unixbhaskar@gmail.com>

On 3/21/21 11:22 PM, Bhaskar Chowdhury wrote:
> 
> s/struture/structure/
> 
> Signed-off-by: Bhaskar Chowdhury <unixbhaskar@gmail.com>

Acked-by: Randy Dunlap <rdunlap@infradead.org>

> ---
>  Documentation/powerpc/firmware-assisted-dump.rst | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/powerpc/firmware-assisted-dump.rst b/Documentation/powerpc/firmware-assisted-dump.rst
> index 20ea8cdee0aa..6c0ae070ba67 100644
> --- a/Documentation/powerpc/firmware-assisted-dump.rst
> +++ b/Documentation/powerpc/firmware-assisted-dump.rst
> @@ -171,7 +171,7 @@ that were present in CMA region::
>                                             (meta area)    |
>                                                            |
>                                                            |
> -                      Metadata: This area holds a metadata struture whose
> +                      Metadata: This area holds a metadata structure whose
>                        address is registered with f/w and retrieved in the
>                        second kernel after crash, on platforms that support
>                        tags (OPAL). Having such structure with info needed
> --
> 2.31.0
> 


-- 
~Randy


^ permalink raw reply

* Re: [PATCH] powerpc: kernel: Trivial spelling fixes throughout the file head_fsl_booke.S
From: Randy Dunlap @ 2021-03-22 18:50 UTC (permalink / raw)
  To: Bhaskar Chowdhury, mpe, benh, paulus, rppt, akpm,
	christophe.leroy, oss, npiggin, linuxppc-dev, linux-kernel
In-Reply-To: <20210315033732.4173500-1-unixbhaskar@gmail.com>

On 3/14/21 8:37 PM, Bhaskar Chowdhury wrote:
> s/virutal/virtual/
> s/mismach/mismatch/
> 
> Signed-off-by: Bhaskar Chowdhury <unixbhaskar@gmail.com>

Acked-by: Randy Dunlap <rdunlap@infradead.org>

> ---
>  As Randy pointed out I was changing the predefined macro name,so, reverted
>  or leave it alone.
>  Michael,sorry to run down a cold weave in your spine with my stupdity,this is
>  okay.
> 
>  arch/powerpc/kernel/head_fsl_booke.S | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
> index 3f4a40cccef5..a955403247f1 100644
> --- a/arch/powerpc/kernel/head_fsl_booke.S
> +++ b/arch/powerpc/kernel/head_fsl_booke.S
> @@ -113,7 +113,7 @@ _ENTRY(_start);
> 
>  1:
>  	/*
> -	 * We have the runtime (virutal) address of our base.
> +	 * We have the runtime (virtual) address of our base.
>  	 * We calculate our shift of offset from a 64M page.
>  	 * We could map the 64M page we belong to at PAGE_OFFSET and
>  	 * get going from there.
> @@ -497,7 +497,7 @@ END_BTB_FLUSH_SECTION
>  #endif
>  #endif
> 
> -	bne	2f			/* Bail if permission/valid mismach */
> +	bne	2f			/* Bail if permission/valid mismatch */
> 
>  	/* Jump to common tlb load */
>  	b	finish_tlb_load
> @@ -592,7 +592,7 @@ END_BTB_FLUSH_SECTION
>  #endif
>  #endif
> 
> -	bne	2f			/* Bail if permission mismach */
> +	bne	2f			/* Bail if permission mismatch */
> 
>  	/* Jump to common TLB load point */
>  	b	finish_tlb_load
> --
> 2.30.2
> 


-- 
~Randy


^ permalink raw reply

* [PATCH 1/1] powerpc/iommu: Enable remaining IOMMU Pagesizes present in LoPAR
From: Leonardo Bras @ 2021-03-22 19:09 UTC (permalink / raw)
  To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
	Christophe Leroy, Leonardo Bras, Joel Stanley,
	Alexey Kardashevskiy, brking
  Cc: linuxppc-dev, linux-kernel

According to LoPAR, ibm,query-pe-dma-window output named "IO Page Sizes"
will let the OS know all possible pagesizes that can be used for creating a
new DDW.

Currently Linux will only try using 3 of the 8 available options:
4K, 64K and 16M. According to LoPAR, Hypervisor may also offer 32M, 64M,
128M, 256M and 16G.

Enabling bigger pages would be interesting for direct mapping systems
with a lot of RAM, while using less TCE entries.

Signed-off-by: Leonardo Bras <leobras.c@gmail.com>
---
 arch/powerpc/include/asm/iommu.h       |  8 ++++++++
 arch/powerpc/platforms/pseries/iommu.c | 28 +++++++++++++++++++-------
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index deef7c94d7b6..c170048b7a1b 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -19,6 +19,14 @@
 #include <asm/pci-bridge.h>
 #include <asm/asm-const.h>
 
+#define IOMMU_PAGE_SHIFT_16G	34
+#define IOMMU_PAGE_SHIFT_256M	28
+#define IOMMU_PAGE_SHIFT_128M	27
+#define IOMMU_PAGE_SHIFT_64M	26
+#define IOMMU_PAGE_SHIFT_32M	25
+#define IOMMU_PAGE_SHIFT_16M	24
+#define IOMMU_PAGE_SHIFT_64K	16
+
 #define IOMMU_PAGE_SHIFT_4K      12
 #define IOMMU_PAGE_SIZE_4K       (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K)
 #define IOMMU_PAGE_MASK_4K       (~((1 << IOMMU_PAGE_SHIFT_4K) - 1))
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 9fc5217f0c8e..02958e80aa91 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1099,6 +1099,24 @@ static void reset_dma_window(struct pci_dev *dev, struct device_node *par_dn)
 			 ret);
 }
 
+/* Returns page shift based on "IO Page Sizes" output at ibm,query-pe-dma-window. SeeL LoPAR */
+static int iommu_get_page_shift(u32 query_page_size)
+{
+	const int shift[] = {IOMMU_PAGE_SHIFT_4K,   IOMMU_PAGE_SHIFT_64K,  IOMMU_PAGE_SHIFT_16M,
+			     IOMMU_PAGE_SHIFT_32M,  IOMMU_PAGE_SHIFT_64M,  IOMMU_PAGE_SHIFT_128M,
+			     IOMMU_PAGE_SHIFT_256M, IOMMU_PAGE_SHIFT_16G};
+	int i = ARRAY_SIZE(shift) - 1;
+
+	/* Looks for the largest page size supported */
+	for (; i >= 0; i--) {
+		if (query_page_size & (1 << i))
+			return shift[i];
+	}
+
+	/* No valid page size found. */
+	return 0;
+}
+
 /*
  * If the PE supports dynamic dma windows, and there is space for a table
  * that can map all pages in a linear offset, then setup such a table,
@@ -1206,13 +1224,9 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
 			goto out_failed;
 		}
 	}
-	if (query.page_size & 4) {
-		page_shift = 24; /* 16MB */
-	} else if (query.page_size & 2) {
-		page_shift = 16; /* 64kB */
-	} else if (query.page_size & 1) {
-		page_shift = 12; /* 4kB */
-	} else {
+
+	page_shift = iommu_get_page_shift(query.page_size);
+	if (!page_shift) {
 		dev_dbg(&dev->dev, "no supported direct page size in mask %x",
 			  query.page_size);
 		goto out_failed;
-- 
2.29.2


^ permalink raw reply related

* Re: [PATCH next v1 2/3] printk: remove safe buffers
From: John Ogness @ 2021-03-22 21:58 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Rafael Aquini, Alexey Kardashevskiy, Paul Mackerras, Tiezhu Yang,
	Peter Zijlstra, Yue Hu, Jordan Niethe, Kees Cook,
	Paul E. McKenney, Alistair Popple, Guilherme G. Piccoli,
	Nicholas Piggin, Steven Rostedt, Thomas Gleixner, kexec,
	linux-kernel, Sergey Senozhatsky, Eric Biederman, Andrew Morton,
	linuxppc-dev, Cédric Le Goater
In-Reply-To: <YFjbwxhZNnC52aSP@alley>

On 2021-03-22, Petr Mladek <pmladek@suse.com> wrote:
> On Mon 2021-03-22 12:16:15, John Ogness wrote:
>> On 2021-03-21, Sergey Senozhatsky <senozhatsky@chromium.org> wrote:
>> >> @@ -369,7 +70,10 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
>> >>  	 * Use the main logbuf even in NMI. But avoid calling console
>> >>  	 * drivers that might have their own locks.
>> >>  	 */
>> >> -	if ((this_cpu_read(printk_context) & PRINTK_NMI_DIRECT_CONTEXT_MASK)) {
>> >> +	if (this_cpu_read(printk_context) &
>> >> +	    (PRINTK_NMI_DIRECT_CONTEXT_MASK |
>> >> +	     PRINTK_NMI_CONTEXT_MASK |
>> >> +	     PRINTK_SAFE_CONTEXT_MASK)) {
>> >
>> > Do we need printk_nmi_direct_enter/exit() and
>> > PRINTK_NMI_DIRECT_CONTEXT_MASK?  Seems like all printk_safe() paths
>> > are now DIRECT - we store messages to the prb, but don't call console
>> > drivers.
>>
>> I was planning on waiting until the kthreads are introduced, in which
>> case printk_safe.c is completely removed.
>
> You want to keep printk_safe() context because it prevents calling
> consoles even in normal context. Namely, it prevents deadlock by
> recursively taking, for example, sem->lock in console_lock() or
> console_owner_lock in console_trylock_spinning(). Am I right?

Correct.

>> But I suppose I could switch
>> the 1 printk_nmi_direct_enter() user to printk_nmi_enter() so that
>> PRINTK_NMI_DIRECT_CONTEXT_MASK can be removed now. I would do this in a
>> 4th patch of the series.
>
> Yes, please unify the PRINTK_NMI_CONTEXT. One is enough.

Agreed. (But I'll go even further. See below.)

> I wonder if it would make sense to go even further at this stage.
> There will still be 4 contexts that modify the printk behavior after
> this patchset:
>
>   + printk_count set by printk_enter()/exit()
>       + prevents: infinite recursion
>       + context: any context
>       + action: skips entire printk at 3rd recursion level
>
>   + prink_context set by printk_safe_enter()/exit()
>       + prevents: dead lock caused by recursion into some
> 		console code in any context
>       + context: any
>       + action: skips console call at 1st recursion level

Technically, at this point printk_safe_enter() behavior is identical to
printk_nmi_enter(). Namely, prevent any recursive printk calls from
calling into the console code.

>   + printk_context set by printk_nmi_enter()/exit()
>       + prevents: dead lock caused by any console lock recursion
>       + context: NMI
>       + action: skips console calls at 0th recursion level
>
>   + kdb_trap_printk
>       + redirects printk() to kdb_printk() in kdb context
>
>
> What is possible?
>
> 1. We could get rid of printk_nmi_enter()/exit() and
>    PRINTK_NMI_CONTEXT completely already now. It is enough
>    to check in_nmi() in printk_func().
>
>    printk_nmi_enter() was added by the commit 42a0bb3f71383b457a7db362
>    ("printk/nmi: generic solution for safe printk in NMI"). It was
>    really needed to modify @printk_func pointer.
>
>    We did not remove it later when printk_function became a real
>    function. The idea was to track all printk contexts in a single
>    variable. But we never added kdb context.
>
>    It might make sense to remove it now. Peter Zijstra would be happy.
>    There already were some churns with tracking printk_context in NMI.
>    For example, see
>    https://lore.kernel.org/r/20200219150744.428764577@infradead.org
>
>    IMHO, it does not make sense to wait until the entire console-stuff
>    rework is done in this case.

Agreed. in_nmi() within vprintk_emit() is enough to detect if the
console code should be skipped:

    if (!in_sched && !in_nmi()) {
        ...
    }

> 2. I thought about unifying printk_safe_enter()/exit() and
>    printk_enter()/exit(). They both count recursion with
>    IRQs disabled, have similar name. But they are used
>    different way.
>
>    But better might be to rename printk_safe_enter()/exit() to
>    console_enter()/exit() or to printk_deferred_enter()/exit().
>    It would make more clear what it does now. And it might help
>    to better distinguish it from the new printk_enter()/exit().
>
>    This patchset actually splits the original printk_safe()
>    functionality into two:
>
>        + printk_count prevents infinite recursion
>        + printk_deferred_enter() deffers console handling.
>
>    I am not sure if it is worth it. But it might help people (even me)
>    when digging into the printk history. Different name will help to
>    understand the functionality at the given time.

I am also not sure if it is worth the extra "noise" just to give the
function a more appropriate name. The plan is to remove it completely
soon anyway. My vote is to leave the name as it is.

But I am willing to do the rename in an addtional patch if you
want. printk_deferred_enter() sounds fine to me. Please confirm if you
want me to do this.

John Ogness

^ permalink raw reply

* Re: [PATCH 1/1] hotplug-cpu.c: show 'last online CPU' error in dlpar_cpu_remove()
From: Daniel Henrique Barboza @ 2021-03-22 23:30 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev
In-Reply-To: <87a6qz8juk.fsf@mpe.ellerman.id.au>



On 3/19/21 8:26 AM, Michael Ellerman wrote:
> Daniel Henrique Barboza <danielhb413@gmail.com> writes:
>> Ping
>>
>> On 3/5/21 2:38 PM, Daniel Henrique Barboza wrote:
>>> Of all the reasons that dlpar_cpu_remove() can fail, the 'last online
>>> CPU' is one that can be caused directly by the user offlining CPUs
>>> in a partition/virtual machine that has hotplugged CPUs. Trying to
>>> reclaim a hotplugged CPU can fail if the CPU is now the last online in
>>> the system. This is easily reproduced using QEMU [1].
> 
> Sorry, I saw this earlier and never got around to replying.

No problem. Thanks for the review!

> 
> I'm wondering if we neet to catch it earlier, ie. in
> dlpar_offline_cpu().
> 
> By the time we return to dlpar_cpu_remove() we've dropped the
> cpu_add_remove_lock (cpu_maps_update_done), so num_online_cpus() could
> change out from under us, meaning the num_online_cpus() == 1 check might
> trigger incorrectly (or vice versa).
> 
> Something like the patch below (completely untested :D)

Makes sense. I'll try it out to see if it works.

> 
> And writing that patch makes me wonder, is == 1 the right check?
> 
> In most cases we'll remove all but one thread of the core, but we'll
> fail on the last thread. Leaving that core effectively stuck in SMT1. Is
> that useful behaviour? Should we instead check at the start that we can
> remove all threads of the core without going to zero online CPUs?

I think it's ok to allow SMT1 cores, speaking from QEMU perspective.
QEMU does not have a "core hotunplug" operation where the whole core is
hotunplugged at once. The CPU hotplug/unplug operations are done as single
CPU thread add/removal. If the user wants to run 4 cores, all of them with
SMT1, QEMU will allow it.

Libvirt does not operate with the core granularity either - you can specify
the amount of vcpus the guest should run with, and Libvirt will send
hotplug/unplug requests to QEMU to match the desired value. It doesn't
bother with how many threads of a core were offlined or not.


Thanks,


DHB



> 
> cheers
> 
> 
> diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
> index 12cbffd3c2e3..498c22331ac8 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
> @@ -271,6 +271,12 @@ static int dlpar_offline_cpu(struct device_node *dn)
>   			if (!cpu_online(cpu))
>   				break;
>   
> +			if (num_online_cpus() == 1) {
> +				pr_warn("Unable to remove last online CPU %pOFn\n", dn);
> +				rc = EBUSY;
> +				goto out_unlock;
> +			}
> +
>   			cpu_maps_update_done();
>   			rc = device_offline(get_cpu_device(cpu));
>   			if (rc)
> @@ -283,6 +289,7 @@ static int dlpar_offline_cpu(struct device_node *dn)
>   				thread);
>   		}
>   	}
> +out_unlock:
>   	cpu_maps_update_done();
>   
>   out:
> 

^ permalink raw reply

* Re: [PATCH 00/10] Move 64e to new interrupt return code
From: Daniel Axtens @ 2021-03-22 23:45 UTC (permalink / raw)
  To: Nicholas Piggin, linuxppc-dev; +Cc: Scott Wood, Nicholas Piggin
In-Reply-To: <20210315031716.3940350-1-npiggin@gmail.com>

Hi Nick,

> Since RFC this is rebased on Christophe's v3 ppc32 conversion, and
> has fixed up small details, and then adds some powerpc-wide
> cleanups at the end.
>
> Tested on qemu only (QEMU e500), which is not ideal for interrupt
> handling particularly the critical interrupts which I don't know
> whether it can generate.

I tested this on a T4240RDB with:

stress-ng --class interrupts --seq 0 -t 5

There are some problems that occur only when testing with your series. I
haven't made any attempt to debug them yet.

stress-ng: info:  [3101] unsuccessful run completed in 6352.60s (1 hour, 45 mins, 52.60 secs)
stress-ng: fail:  [3101] aio instance 0 corrupted bogo-ops counter, 7542705 vs 0
stress-ng: fail:  [3101] aio instance 0 hash error in bogo-ops counter and run flag, 359866039 vs 0
stress-ng: fail:  [3101] aio instance 17 corrupted bogo-ops counter, 7638823 vs 0
stress-ng: fail:  [3101] aio instance 17 hash error in bogo-ops counter and run flag, 2001558423 vs 0
stress-ng: fail:  [3101] aio instance 30 corrupted bogo-ops counter, 8192545 vs 0
info: 5 failures reached, aborting stress process
stress-ng: fail:  [3101] aio instance 30 hash error in bogo-ops counter and run flag, 3023200976 vs 0
stress-ng: fail:  [3101] pidfd instance 25 corrupted bogo-ops counter, 116476 vs 0
stress-ng: fail:  [3101] pidfd instance 25 hash error in bogo-ops counter and run flag, 1964630417 vs 0
stress-ng: fail:  [3101] sigabrt instance 3 corrupted bogo-ops counter, 95662 vs 0
stress-ng: fail:  [3101] sigabrt instance 3 hash error in bogo-ops counter and run flag, 1321243721 vs 0
stress-ng: fail:  [3101] sigabrt instance 9 corrupted bogo-ops counter, 92858 vs 0
stress-ng: fail:  [3101] sigabrt instance 9 hash error in bogo-ops counter and run flag, 3835381330 vs 0
stress-ng: fail:  [3101] sigabrt instance 11 corrupted bogo-ops counter, 98333 vs 0
stress-ng: fail:  [3101] sigabrt instance 11 hash error in bogo-ops counter and run flag, 3447969030 vs 0
stress-ng: fail:  [3101] sigabrt instance 14 corrupted bogo-ops counter, 96995 vs 0
stress-ng: fail:  [3101] sigabrt instance 14 hash error in bogo-ops counter and run flag, 2621581502 vs 0
stress-ng: fail:  [3101] sigabrt instance 16 corrupted bogo-ops counter, 97464 vs 0
stress-ng: fail:  [3101] sigabrt instance 16 hash error in bogo-ops counter and run flag, 3422440538 vs 0
stress-ng: fail:  [3101] sigabrt instance 19 corrupted bogo-ops counter, 96044 vs 0
stress-ng: fail:  [3101] sigabrt instance 19 hash error in bogo-ops counter and run flag, 511989935 vs 0
stress-ng: fail:  [3101] sigabrt instance 20 corrupted bogo-ops counter, 96018 vs 0
stress-ng: fail:  [3101] sigabrt instance 20 hash error in bogo-ops counter and run flag, 2348631606 vs 0
stress-ng: fail:  [3101] sigabrt instance 23 corrupted bogo-ops counter, 95252 vs 0
stress-ng: fail:  [3101] sigabrt instance 23 hash error in bogo-ops counter and run flag, 2302430489 vs 0
stress-ng: fail:  [3101] sigabrt instance 26 corrupted bogo-ops counter, 99151 vs 0
stress-ng: fail:  [3101] sigabrt instance 26 hash error in bogo-ops counter and run flag, 2882282932 vs 0
stress-ng: fail:  [3101] sigabrt instance 27 corrupted bogo-ops counter, 95434 vs 0
stress-ng: fail:  [3101] sigabrt instance 27 hash error in bogo-ops counter and run flag, 260112434 vs 0
stress-ng: fail:  [3101] sigabrt instance 28 corrupted bogo-ops counter, 97138 vs 0
stress-ng: fail:  [3101] sigabrt instance 28 hash error in bogo-ops counter and run flag, 2822283734 vs 0
stress-ng: fail:  [3101] sigabrt instance 30 corrupted bogo-ops counter, 97728 vs 0
stress-ng: fail:  [3101] sigabrt instance 30 hash error in bogo-ops counter and run flag, 738567801 vs 0
stress-ng: fail:  [3101] sigabrt instance 31 corrupted bogo-ops counter, 96368 vs 0
stress-ng: fail:  [3101] sigabrt instance 31 hash error in bogo-ops counter and run flag, 1663873592 vs 0
stress-ng: fail:  [3101] sigio instance 0 corrupted bogo-ops counter, 1141 vs 0
stress-ng: fail:  [3101] sigio instance 0 hash error in bogo-ops counter and run flag, 3981634025 vs 0
stress-ng: fail:  [3101] sigio instance 1 corrupted bogo-ops counter, 1323 vs 0
stress-ng: fail:  [3101] sigio instance 1 hash error in bogo-ops counter and run flag, 2384922462 vs 0
stress-ng: fail:  [3101] sigio instance 2 corrupted bogo-ops counter, 876 vs 0
stress-ng: fail:  [3101] sigio instance 2 hash error in bogo-ops counter and run flag, 2730635354 vs 0
stress-ng: fail:  [3101] sigio instance 3 corrupted bogo-ops counter, 3391 vs 0
stress-ng: fail:  [3101] sigio instance 3 hash error in bogo-ops counter and run flag, 3893594528 vs 0
stress-ng: fail:  [3101] sigio instance 4 corrupted bogo-ops counter, 988 vs 0
stress-ng: fail:  [3101] sigio instance 4 hash error in bogo-ops counter and run flag, 2252189661 vs 0
stress-ng: fail:  [3101] sigio instance 5 corrupted bogo-ops counter, 4158 vs 0
stress-ng: fail:  [3101] sigio instance 5 hash error in bogo-ops counter and run flag, 908770141 vs 0
stress-ng: fail:  [3101] sigio instance 6 corrupted bogo-ops counter, 657 vs 0
stress-ng: fail:  [3101] sigio instance 6 hash error in bogo-ops counter and run flag, 3022228667 vs 0
stress-ng: fail:  [3101] sigio instance 7 corrupted bogo-ops counter, 239 vs 0
stress-ng: fail:  [3101] sigio instance 7 hash error in bogo-ops counter and run flag, 2339545388 vs 0
stress-ng: fail:  [3101] sigio instance 8 corrupted bogo-ops counter, 183062 vs 0
stress-ng: fail:  [3101] sigio instance 8 hash error in bogo-ops counter and run flag, 2294439106 vs 0
stress-ng: fail:  [3101] sigio instance 9 corrupted bogo-ops counter, 946 vs 0
stress-ng: fail:  [3101] sigio instance 9 hash error in bogo-ops counter and run flag, 2990832529 vs 0
stress-ng: fail:  [3101] sigio instance 10 corrupted bogo-ops counter, 2799 vs 0
stress-ng: fail:  [3101] sigio instance 10 hash error in bogo-ops counter and run flag, 1781985030 vs 0
stress-ng: fail:  [3101] sigio instance 11 corrupted bogo-ops counter, 2705 vs 0
stress-ng: fail:  [3101] sigio instance 11 hash error in bogo-ops counter and run flag, 3301490000 vs 0
stress-ng: fail:  [3101] sigio instance 21 corrupted bogo-ops counter, 238787 vs 0
stress-ng: fail:  [3101] sigio instance 21 hash error in bogo-ops counter and run flag, 2490210165 vs 0
stress-ng: fail:  [3101] sigio instance 28 corrupted bogo-ops counter, 1020 vs 0
stress-ng: fail:  [3101] sigio instance 28 hash error in bogo-ops counter and run flag, 3260422232 vs 0
stress-ng: fail:  [3101] metrics-check: stressor metrics corrupted, data is compromised

It looks like this is paired with some segfaults in dmesg:

stress-ng-pidfd[4417]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-pidfd[4417]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-pidfd[4417]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748349]: segfault (11) at 800100 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigab[3748349]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748390]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1
stress-ng-sigab[3748405]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigab[3748405]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748405]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748427]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1
stress-ng-sigab[3748376]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1
in stress-ng[107e8d000+3000]
in stress-ng[107e8d000+3000]
stress-ng-sigab[3748427]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748376]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748427]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748376]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748460]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigab[3748460]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748460]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748434]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigab[3748434]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748434]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748367]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigab[3748367]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748367]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748349]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
in stress-ng[107e8d000+3000]
stress-ng-sigab[3748507]: segfault (11) at 800100 nip 107e8fb14 lr 107e8fb04 code 1

in stress-ng[107e8d000+3000]
stress-ng-sigab[3748390]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 

stress-ng-sigab[3748491]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigab[3748491]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748491]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748390]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigab[3748507]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigab[3748507]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
show_signal_msg: 3 callbacks suppressed
stress-ng-sigio[2635277]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1
stress-ng-sigio[2635278]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1
stress-ng-sigio[2635279]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635279]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635279]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigio[2635280]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635280]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635280]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigio[2635283]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635283]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635283]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigio[2635285]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635285]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635285]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigio[2635289]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635289]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635289]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
in stress-ng[107e8d000+3000]
stress-ng-sigio[2635293]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635293]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635293]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigio[2635292]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635292]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635292]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigio[2635315]: segfault (11) at 800000 nip 107e8fb14 lr 107e8fb04 code 1 in stress-ng[107e8d000+3000]
stress-ng-sigio[2635315]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635315]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
in stress-ng[107e8d000+3000]

stress-ng-sigio[2635278]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635277]: code: 7d4903a6 e8490008 4e800421 e8410028 7c691b78 386100ac 912100ac 4bfc3be1 
stress-ng-sigio[2635278]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 
stress-ng-sigio[2635277]: code: 60000000 812100ac 2c090000 40820014 <e90f0000> 39200001 993c0940 99280008 

In one run, I had problems with a hardware interrupt, but I haven't seen
it reoccur so I can't be sure it came from your series:


mmc0: Timeout waiting for hardware cmd interrupt.        
mmc0: sdhci: ============ SDHCI REGISTER DUMP ===========
mmc0: sdhci: Sys addr:  0x00000000 | Version:  0x00001301
mmc0: sdhci: Blk size:  0x00000000 | Blk cnt:  0x00000000
mmc0: sdhci: Argument:  0x00000c00 | Trn mode: 0x00000000
mmc0: sdhci: Present:   0x01f00008 | Host ctl: 0x00000020
mmc0: sdhci: Power:     0x00000000 | Blk gap:  0x00000000
mmc0: sdhci: Wake-up:   0x00000000 | Clock:    0x000020e8
mmc0: sdhci: Timeout:   0x00000000 | Int stat: 0x00010001
mmc0: sdhci: Int enab:  0x007f0007 | Sig enab: 0x007f0003
mmc0: sdhci: ACmd stat: 0x00000000 | Slot int: 0x00001402
mmc0: sdhci: Caps:      0x04fa0000 | Caps_1:   0x00000000
mmc0: sdhci: Cmd:       0x0000341a | Max curr: 0x00000000
mmc0: sdhci: Resp[0]:   0x00000000 | Resp[1]:  0x00000000
mmc0: sdhci: Resp[2]:   0x00000000 | Resp[3]:  0x00000000
mmc0: sdhci: Host ctl2: 0x00000000                       
mmc0: sdhci: ADMA Err:  0x00000000 | ADMA Ptr: 0x00000000
mmc0: sdhci: ============================================
mmc0: Timeout waiting for hardware cmd interrupt. 

Let me know if you'd like me to run any further tests.

Kind regards,
Daniel

>
> Thanks,
> Nick
>
> Nicholas Piggin (10):
>   powerpc/syscall: switch user_exit_irqoff and trace_hardirqs_off order
>   powerpc/64e/interrupt: always save nvgprs on interrupt
>   powerpc/64e/interrupt: use new interrupt return
>   powerpc/64e/interrupt: NMI save irq soft-mask state in C
>   powerpc/64e/interrupt: reconcile irq soft-mask state in C
>   powerpc/64e/interrupt: Use new interrupt context tracking scheme
>   powerpc/64e/interrupt: handle bad_page_fault in C
>   powerpc: clean up do_page_fault
>   powerpc: remove partial register save logic
>   powerpc: move norestart trap flag to bit 0
>
>  arch/powerpc/include/asm/asm-prototypes.h |   2 -
>  arch/powerpc/include/asm/bug.h            |   4 +-
>  arch/powerpc/include/asm/interrupt.h      |  66 ++--
>  arch/powerpc/include/asm/ptrace.h         |  36 +-
>  arch/powerpc/kernel/align.c               |   6 -
>  arch/powerpc/kernel/entry_64.S            |  40 +-
>  arch/powerpc/kernel/exceptions-64e.S      | 425 ++--------------------
>  arch/powerpc/kernel/interrupt.c           |  22 +-
>  arch/powerpc/kernel/irq.c                 |  76 ----
>  arch/powerpc/kernel/process.c             |  12 -
>  arch/powerpc/kernel/ptrace/ptrace-view.c  |  21 --
>  arch/powerpc/kernel/ptrace/ptrace.c       |   2 -
>  arch/powerpc/kernel/ptrace/ptrace32.c     |   4 -
>  arch/powerpc/kernel/signal_32.c           |   3 -
>  arch/powerpc/kernel/signal_64.c           |   2 -
>  arch/powerpc/kernel/traps.c               |  14 +-
>  arch/powerpc/lib/sstep.c                  |   4 -
>  arch/powerpc/mm/book3s64/hash_utils.c     |  16 +-
>  arch/powerpc/mm/fault.c                   |  28 +-
>  arch/powerpc/xmon/xmon.c                  |  23 +-
>  20 files changed, 130 insertions(+), 676 deletions(-)
>
> -- 
> 2.23.0

^ permalink raw reply

* Re: [PATCH] powerpc/asm: Fix a typo
From: Michael Ellerman @ 2021-03-22 23:48 UTC (permalink / raw)
  To: Randy Dunlap, Bhaskar Chowdhury, benh, paulus, linuxppc-dev,
	linux-kernel
In-Reply-To: <96eda8ce-1d89-1491-51a2-92ba9883912b@infradead.org>

Randy Dunlap <rdunlap@infradead.org> writes:
> On 3/22/21 4:32 AM, Bhaskar Chowdhury wrote:
>> 
>> s/poiner/pointer/
>> 
>> Signed-off-by: Bhaskar Chowdhury <unixbhaskar@gmail.com>
>
> Acked-by: Randy Dunlap <rdunlap@infradead.org>
>
> However, it would be a GOOD THING to collect multiple similar
> patches that are in e.g. arch/powerpc/ and send them as one patch
> instead of many little patches.

Yes.

Please send me one patch for all of the spelling issues you can
currently find in arch/powerpc.

cheers

^ permalink raw reply

* Re: [PATCH 3/3] powerpc/mm/hash: Avoid multiple HPT resize-downs on memory hotunplug
From: David Gibson @ 2021-03-22 23:45 UTC (permalink / raw)
  To: Leonardo Bras
  Cc: Nathan Lynch, David Hildenbrand, Scott Cheloha, linux-kernel,
	linuxppc-dev, Nicholas Piggin, Bharata B Rao, Paul Mackerras,
	Sandipan Das, Aneesh Kumar K.V, Andrew Morton, Laurent Dufour,
	Logan Gunthorpe, Dan Williams, Mike Rapoport
In-Reply-To: <20210312072940.598696-4-leobras.c@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 9150 bytes --]

On Fri, Mar 12, 2021 at 04:29:41AM -0300, Leonardo Bras wrote:
> During memory hotunplug, after each LMB is removed, the HPT may be
> resized-down if it would map a max of 4 times the current amount of memory.
> (2 shifts, due to introduced histeresis)
> 
> It usually is not an issue, but it can take a lot of time if HPT
> resizing-down fails. This happens  because resize-down failures
> usually repeat at each LMB removal, until there are no more bolted entries
> conflict, which can take a while to happen.
> 
> This can be solved by doing a single HPT resize at the end of memory
> hotunplug, after all requested entries are removed.
> 
> To make this happen, it's necessary to temporarily disable all HPT
> resize-downs before hotunplug, re-enable them after hotunplug ends,
> and then resize-down HPT to the current memory size.
> 
> As an example, hotunplugging 256GB from a 385GB guest took 621s without
> this patch, and 100s after applied.
> 
> Signed-off-by: Leonardo Bras <leobras.c@gmail.com>
> ---
>  arch/powerpc/include/asm/book3s/64/hash.h     |  2 ++
>  arch/powerpc/include/asm/sparsemem.h          |  2 ++
>  arch/powerpc/mm/book3s64/hash_utils.c         | 28 +++++++++++++++++++
>  arch/powerpc/mm/book3s64/pgtable.c            | 12 ++++++++
>  .../platforms/pseries/hotplug-memory.c        | 16 +++++++++++
>  5 files changed, 60 insertions(+)
> 
> diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h
> index 843b0a178590..f92697c107f7 100644
> --- a/arch/powerpc/include/asm/book3s/64/hash.h
> +++ b/arch/powerpc/include/asm/book3s/64/hash.h
> @@ -256,6 +256,8 @@ int hash__create_section_mapping(unsigned long start, unsigned long end,
>  int hash__remove_section_mapping(unsigned long start, unsigned long end);
>  
>  void hash_memory_batch_expand_prepare(unsigned long newsize);
> +void hash_memory_batch_shrink_begin(void);
> +void hash_memory_batch_shrink_end(void);
>  
>  #endif /* !__ASSEMBLY__ */
>  #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/include/asm/sparsemem.h b/arch/powerpc/include/asm/sparsemem.h
> index 16b5f5300c84..a7a8a0d070fc 100644
> --- a/arch/powerpc/include/asm/sparsemem.h
> +++ b/arch/powerpc/include/asm/sparsemem.h
> @@ -18,6 +18,8 @@ extern int memory_add_physaddr_to_nid(u64 start);
>  #define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
>  
>  void memory_batch_expand_prepare(unsigned long newsize);
> +void memory_batch_shrink_begin(void);
> +void memory_batch_shrink_end(void);
>  
>  #ifdef CONFIG_NUMA
>  extern int hot_add_scn_to_nid(unsigned long scn_addr);
> diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
> index 1f6aa0bf27e7..e16f207de8e4 100644
> --- a/arch/powerpc/mm/book3s64/hash_utils.c
> +++ b/arch/powerpc/mm/book3s64/hash_utils.c
> @@ -794,6 +794,9 @@ static unsigned long __init htab_get_table_size(void)
>  }
>  
>  #ifdef CONFIG_MEMORY_HOTPLUG
> +
> +atomic_t hpt_resize_disable = ATOMIC_INIT(0);
> +
>  static int resize_hpt_for_hotplug(unsigned long new_mem_size, bool shrinking)
>  {
>  	unsigned target_hpt_shift;
> @@ -805,6 +808,10 @@ static int resize_hpt_for_hotplug(unsigned long new_mem_size, bool shrinking)
>  
>  	if (shrinking) {
>  
> +		/* When batch removing entries, only resizes HPT at the end. */
> +		if (atomic_read_acquire(&hpt_resize_disable))
> +			return 0;
> +

I'm not quite convinced by this locking.  Couldn't hpt_resize_disable
be set after this point, but while you're still inside
resize_hpt_for_hotplug()?  Probably better to use an explicit mutex
(and mutex_trylock()) to make the critical sections clearer.

Except... do we even need the fancy mechanics to suppress the resizes
in one place to do them elswhere.  Couldn't we just replace the
existing resize calls with the batched ones?

>  		/*
>  		 * To avoid lots of HPT resizes if memory size is fluctuating
>  		 * across a boundary, we deliberately have some hysterisis
> @@ -872,6 +879,27 @@ void hash_memory_batch_expand_prepare(unsigned long newsize)
>  		pr_warn("Hash collision while resizing HPT\n");
>  	}
>  }
> +
> +void hash_memory_batch_shrink_begin(void)
> +{
> +	/* Disable HPT resize-down during hot-unplug */
> +	atomic_set_release(&hpt_resize_disable, 1);
> +}
> +
> +void hash_memory_batch_shrink_end(void)
> +{
> +	unsigned long newsize;
> +
> +	/* Re-enables HPT resize-down after hot-unplug */
> +	atomic_set_release(&hpt_resize_disable, 0);
> +
> +	newsize = memblock_phys_mem_size();
> +	/* Resize to smallest SHIFT possible */
> +	while (resize_hpt_for_hotplug(newsize, true) == -ENOSPC) {
> +		newsize *= 2;

As noted earlier, doing this without an explicit cap on the new hpt
size (of the existing size) this makes me nervous.  Less so, but doing
the calculations on memory size, rather than explictly on HPT size /
HPT order also seems kinda clunky.

> +		pr_warn("Hash collision while resizing HPT\n");
> +	}
> +}
>  #endif /* CONFIG_MEMORY_HOTPLUG */
>  
>  static void __init hash_init_partition_table(phys_addr_t hash_table,
> diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
> index f1cd8af0f67f..e01681e22e00 100644
> --- a/arch/powerpc/mm/book3s64/pgtable.c
> +++ b/arch/powerpc/mm/book3s64/pgtable.c
> @@ -199,6 +199,18 @@ void memory_batch_expand_prepare(unsigned long newsize)
>  	if (!radix_enabled())
>  		hash_memory_batch_expand_prepare(newsize);
>  }
> +
> +void memory_batch_shrink_begin(void)
> +{
> +	if (!radix_enabled())
> +		hash_memory_batch_shrink_begin();
> +}
> +
> +void memory_batch_shrink_end(void)
> +{
> +	if (!radix_enabled())
> +		hash_memory_batch_shrink_end();
> +}

Again, these wrappers don't seem particularly useful to me.

>  #endif /* CONFIG_MEMORY_HOTPLUG */
>  
>  void __init mmu_partition_table_init(void)
> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
> index 353c71249214..9182fb5b5c01 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> @@ -425,6 +425,8 @@ static int dlpar_memory_remove_by_count(u32 lmbs_to_remove)
>  		return -EINVAL;
>  	}
>  
> +	memory_batch_shrink_begin();
> +
>  	for_each_drmem_lmb(lmb) {
>  		rc = dlpar_remove_lmb(lmb);
>  		if (rc)
> @@ -470,6 +472,8 @@ static int dlpar_memory_remove_by_count(u32 lmbs_to_remove)
>  		rc = 0;
>  	}
>  
> +	memory_batch_shrink_end();
> +
>  	return rc;
>  }
>  
> @@ -481,6 +485,8 @@ static int dlpar_memory_remove_by_index(u32 drc_index)
>  
>  	pr_debug("Attempting to hot-remove LMB, drc index %x\n", drc_index);
>  
> +	memory_batch_shrink_begin();
> +
>  	lmb_found = 0;
>  	for_each_drmem_lmb(lmb) {
>  		if (lmb->drc_index == drc_index) {
> @@ -502,6 +508,8 @@ static int dlpar_memory_remove_by_index(u32 drc_index)
>  	else
>  		pr_debug("Memory at %llx was hot-removed\n", lmb->base_addr);
>  
> +	memory_batch_shrink_end();

remove_by_index only removes a single LMB, so there's no real point to
batching here.

>  	return rc;
>  }
>  
> @@ -532,6 +540,8 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index)
>  	if (lmbs_available < lmbs_to_remove)
>  		return -EINVAL;
>  
> +	memory_batch_shrink_begin();
> +
>  	for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
>  		if (!(lmb->flags & DRCONF_MEM_ASSIGNED))
>  			continue;
> @@ -572,6 +582,8 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, u32 drc_index)
>  		}
>  	}
>  
> +	memory_batch_shrink_end();
> +
>  	return rc;
>  }
>  
> @@ -700,6 +712,7 @@ static int dlpar_memory_add_by_count(u32 lmbs_to_add)
>  	if (lmbs_added != lmbs_to_add) {
>  		pr_err("Memory hot-add failed, removing any added LMBs\n");
>  
> +		memory_batch_shrink_begin();


The effect of these on the memory grow path is far from clear.

>  		for_each_drmem_lmb(lmb) {
>  			if (!drmem_lmb_reserved(lmb))
>  				continue;
> @@ -713,6 +726,7 @@ static int dlpar_memory_add_by_count(u32 lmbs_to_add)
>  
>  			drmem_remove_lmb_reservation(lmb);
>  		}
> +		memory_batch_shrink_end();
>  		rc = -EINVAL;
>  	} else {
>  		for_each_drmem_lmb(lmb) {
> @@ -814,6 +828,7 @@ static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index)
>  	if (rc) {
>  		pr_err("Memory indexed-count-add failed, removing any added LMBs\n");
>  
> +		memory_batch_shrink_begin();
>  		for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {
>  			if (!drmem_lmb_reserved(lmb))
>  				continue;
> @@ -827,6 +842,7 @@ static int dlpar_memory_add_by_ic(u32 lmbs_to_add, u32 drc_index)
>  
>  			drmem_remove_lmb_reservation(lmb);
>  		}
> +		memory_batch_shrink_end();
>  		rc = -EINVAL;
>  	} else {
>  		for_each_drmem_lmb_in_range(lmb, start_lmb, end_lmb) {

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH] xsysace: Remove SYSACE driver
From: Davidlohr Bueso @ 2021-03-23  0:04 UTC (permalink / raw)
  To: Michal Simek
  Cc: Jens Axboe, devicetree, monstr, YueHaibing, linux-kernel,
	Rob Herring, linux-block, Chris Packham, Paul Mackerras, git,
	linuxppc-dev
In-Reply-To: <ee1fe969905f641f5f97d812ee0cac44c12fe0f6.1604919578.git.michal.simek@xilinx.com>

Hi,

On Mon, 09 Nov 2020, Michal Simek wrote:

>Sysace IP is no longer used on Xilinx PowerPC 405/440 and Microblaze
>systems. The driver is not regularly tested and very likely not working for
>quite a long time that's why remove it.

Is there a reason this patch was never merged? can the driver be removed? I ran
into this as a potential tasklet user that can be replaced/removed.

Thanks,
Davidlohr

>
>Signed-off-by: Michal Simek <michal.simek@xilinx.com>
>---
>
>Based on discussion
>https://lore.kernel.org/linux-arm-kernel/5ab9a2a1-20e3-c7b2-f666-2034df436e74@kernel.dk/
>
>I have grepped the kernel and found any old ppc platform. I have included
>it in this patch to have a discussion about it.
>
>---
> MAINTAINERS                             |    1 -
> arch/microblaze/boot/dts/system.dts     |    8 -
> arch/powerpc/boot/dts/icon.dts          |    7 -
> arch/powerpc/configs/44x/icon_defconfig |    1 -
> drivers/block/Kconfig                   |    6 -
> drivers/block/Makefile                  |    1 -
> drivers/block/xsysace.c                 | 1273 -----------------------
> 7 files changed, 1297 deletions(-)
> delete mode 100644 drivers/block/xsysace.c
>
>diff --git a/MAINTAINERS b/MAINTAINERS
>index cba8ddf87a08..38556c009758 100644
>--- a/MAINTAINERS
>+++ b/MAINTAINERS
>@@ -2741,7 +2741,6 @@ T:	git https://github.com/Xilinx/linux-xlnx.git
> F:	Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml
> F:	Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml
> F:	arch/arm/mach-zynq/
>-F:	drivers/block/xsysace.c
> F:	drivers/clocksource/timer-cadence-ttc.c
> F:	drivers/cpuidle/cpuidle-zynq.c
> F:	drivers/edac/synopsys_edac.c
>diff --git a/arch/microblaze/boot/dts/system.dts b/arch/microblaze/boot/dts/system.dts
>index 5b236527176e..b7ee1056779e 100644
>--- a/arch/microblaze/boot/dts/system.dts
>+++ b/arch/microblaze/boot/dts/system.dts
>@@ -310,14 +310,6 @@ RS232_Uart_1: serial@84000000 {
> 			xlnx,odd-parity = <0x0>;
> 			xlnx,use-parity = <0x0>;
> 		} ;
>-		SysACE_CompactFlash: sysace@83600000 {
>-			compatible = "xlnx,xps-sysace-1.00.a";
>-			interrupt-parent = <&xps_intc_0>;
>-			interrupts = < 4 2 >;
>-			reg = < 0x83600000 0x10000 >;
>-			xlnx,family = "virtex5";
>-			xlnx,mem-width = <0x10>;
>-		} ;
> 		debug_module: debug@84400000 {
> 			compatible = "xlnx,mdm-1.00.d";
> 			reg = < 0x84400000 0x10000 >;
>diff --git a/arch/powerpc/boot/dts/icon.dts b/arch/powerpc/boot/dts/icon.dts
>index fbaa60b8f87a..4fd7a4fbb4fb 100644
>--- a/arch/powerpc/boot/dts/icon.dts
>+++ b/arch/powerpc/boot/dts/icon.dts
>@@ -197,13 +197,6 @@ partition@fa0000 {
> 						reg = <0x00fa0000 0x00060000>;
> 					};
> 				};
>-
>-				SysACE_CompactFlash: sysace@1,0 {
>-					compatible = "xlnx,sysace";
>-					interrupt-parent = <&UIC2>;
>-					interrupts = <24 0x4>;
>-					reg = <0x00000001 0x00000000 0x10000>;
>-				};
> 			};
>
> 			UART0: serial@f0000200 {
>diff --git a/arch/powerpc/configs/44x/icon_defconfig b/arch/powerpc/configs/44x/icon_defconfig
>index 930948a1da76..fb9a15573546 100644
>--- a/arch/powerpc/configs/44x/icon_defconfig
>+++ b/arch/powerpc/configs/44x/icon_defconfig
>@@ -28,7 +28,6 @@ CONFIG_MTD_CFI_AMDSTD=y
> CONFIG_MTD_PHYSMAP_OF=y
> CONFIG_BLK_DEV_RAM=y
> CONFIG_BLK_DEV_RAM_SIZE=35000
>-CONFIG_XILINX_SYSACE=y
> CONFIG_SCSI=y
> CONFIG_BLK_DEV_SD=y
> CONFIG_SCSI_CONSTANTS=y
>diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
>index ecceaaa1a66f..9cb02861298d 100644
>--- a/drivers/block/Kconfig
>+++ b/drivers/block/Kconfig
>@@ -388,12 +388,6 @@ config SUNVDC
>
> source "drivers/s390/block/Kconfig"
>
>-config XILINX_SYSACE
>-	tristate "Xilinx SystemACE support"
>-	depends on 4xx || MICROBLAZE
>-	help
>-	  Include support for the Xilinx SystemACE CompactFlash interface
>-
> config XEN_BLKDEV_FRONTEND
> 	tristate "Xen virtual block device support"
> 	depends on XEN
>diff --git a/drivers/block/Makefile b/drivers/block/Makefile
>index e1f63117ee94..5ddd9370972a 100644
>--- a/drivers/block/Makefile
>+++ b/drivers/block/Makefile
>@@ -19,7 +19,6 @@ obj-$(CONFIG_ATARI_FLOPPY)	+= ataflop.o
> obj-$(CONFIG_AMIGA_Z2RAM)	+= z2ram.o
> obj-$(CONFIG_BLK_DEV_RAM)	+= brd.o
> obj-$(CONFIG_BLK_DEV_LOOP)	+= loop.o
>-obj-$(CONFIG_XILINX_SYSACE)	+= xsysace.o
> obj-$(CONFIG_CDROM_PKTCDVD)	+= pktcdvd.o
> obj-$(CONFIG_SUNVDC)		+= sunvdc.o
> obj-$(CONFIG_BLK_DEV_SKD)	+= skd.o
>diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
>deleted file mode 100644
>index eb8ef65778c3..000000000000
>--- a/drivers/block/xsysace.c
>+++ /dev/null
>@@ -1,1273 +0,0 @@
>-// SPDX-License-Identifier: GPL-2.0-only
>-/*
>- * Xilinx SystemACE device driver
>- *
>- * Copyright 2007 Secret Lab Technologies Ltd.
>- */
>-
>-/*
>- * The SystemACE chip is designed to configure FPGAs by loading an FPGA
>- * bitstream from a file on a CF card and squirting it into FPGAs connected
>- * to the SystemACE JTAG chain.  It also has the advantage of providing an
>- * MPU interface which can be used to control the FPGA configuration process
>- * and to use the attached CF card for general purpose storage.
>- *
>- * This driver is a block device driver for the SystemACE.
>- *
>- * Initialization:
>- *    The driver registers itself as a platform_device driver at module
>- *    load time.  The platform bus will take care of calling the
>- *    ace_probe() method for all SystemACE instances in the system.  Any
>- *    number of SystemACE instances are supported.  ace_probe() calls
>- *    ace_setup() which initialized all data structures, reads the CF
>- *    id structure and registers the device.
>- *
>- * Processing:
>- *    Just about all of the heavy lifting in this driver is performed by
>- *    a Finite State Machine (FSM).  The driver needs to wait on a number
>- *    of events; some raised by interrupts, some which need to be polled
>- *    for.  Describing all of the behaviour in a FSM seems to be the
>- *    easiest way to keep the complexity low and make it easy to
>- *    understand what the driver is doing.  If the block ops or the
>- *    request function need to interact with the hardware, then they
>- *    simply need to flag the request and kick of FSM processing.
>- *
>- *    The FSM itself is atomic-safe code which can be run from any
>- *    context.  The general process flow is:
>- *    1. obtain the ace->lock spinlock.
>- *    2. loop on ace_fsm_dostate() until the ace->fsm_continue flag is
>- *       cleared.
>- *    3. release the lock.
>- *
>- *    Individual states do not sleep in any way.  If a condition needs to
>- *    be waited for then the state much clear the fsm_continue flag and
>- *    either schedule the FSM to be run again at a later time, or expect
>- *    an interrupt to call the FSM when the desired condition is met.
>- *
>- *    In normal operation, the FSM is processed at interrupt context
>- *    either when the driver's tasklet is scheduled, or when an irq is
>- *    raised by the hardware.  The tasklet can be scheduled at any time.
>- *    The request method in particular schedules the tasklet when a new
>- *    request has been indicated by the block layer.  Once started, the
>- *    FSM proceeds as far as it can processing the request until it
>- *    needs on a hardware event.  At this point, it must yield execution.
>- *
>- *    A state has two options when yielding execution:
>- *    1. ace_fsm_yield()
>- *       - Call if need to poll for event.
>- *       - clears the fsm_continue flag to exit the processing loop
>- *       - reschedules the tasklet to run again as soon as possible
>- *    2. ace_fsm_yieldirq()
>- *       - Call if an irq is expected from the HW
>- *       - clears the fsm_continue flag to exit the processing loop
>- *       - does not reschedule the tasklet so the FSM will not be processed
>- *         again until an irq is received.
>- *    After calling a yield function, the state must return control back
>- *    to the FSM main loop.
>- *
>- *    Additionally, the driver maintains a kernel timer which can process
>- *    the FSM.  If the FSM gets stalled, typically due to a missed
>- *    interrupt, then the kernel timer will expire and the driver can
>- *    continue where it left off.
>- *
>- * To Do:
>- *    - Add FPGA configuration control interface.
>- *    - Request major number from lanana
>- */
>-
>-#undef DEBUG
>-
>-#include <linux/module.h>
>-#include <linux/ctype.h>
>-#include <linux/init.h>
>-#include <linux/interrupt.h>
>-#include <linux/errno.h>
>-#include <linux/kernel.h>
>-#include <linux/delay.h>
>-#include <linux/slab.h>
>-#include <linux/blk-mq.h>
>-#include <linux/mutex.h>
>-#include <linux/ata.h>
>-#include <linux/hdreg.h>
>-#include <linux/platform_device.h>
>-#if defined(CONFIG_OF)
>-#include <linux/of_address.h>
>-#include <linux/of_device.h>
>-#include <linux/of_platform.h>
>-#endif
>-
>-MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
>-MODULE_DESCRIPTION("Xilinx SystemACE device driver");
>-MODULE_LICENSE("GPL");
>-
>-/* SystemACE register definitions */
>-#define ACE_BUSMODE (0x00)
>-
>-#define ACE_STATUS (0x04)
>-#define ACE_STATUS_CFGLOCK      (0x00000001)
>-#define ACE_STATUS_MPULOCK      (0x00000002)
>-#define ACE_STATUS_CFGERROR     (0x00000004)	/* config controller error */
>-#define ACE_STATUS_CFCERROR     (0x00000008)	/* CF controller error */
>-#define ACE_STATUS_CFDETECT     (0x00000010)
>-#define ACE_STATUS_DATABUFRDY   (0x00000020)
>-#define ACE_STATUS_DATABUFMODE  (0x00000040)
>-#define ACE_STATUS_CFGDONE      (0x00000080)
>-#define ACE_STATUS_RDYFORCFCMD  (0x00000100)
>-#define ACE_STATUS_CFGMODEPIN   (0x00000200)
>-#define ACE_STATUS_CFGADDR_MASK (0x0000e000)
>-#define ACE_STATUS_CFBSY        (0x00020000)
>-#define ACE_STATUS_CFRDY        (0x00040000)
>-#define ACE_STATUS_CFDWF        (0x00080000)
>-#define ACE_STATUS_CFDSC        (0x00100000)
>-#define ACE_STATUS_CFDRQ        (0x00200000)
>-#define ACE_STATUS_CFCORR       (0x00400000)
>-#define ACE_STATUS_CFERR        (0x00800000)
>-
>-#define ACE_ERROR (0x08)
>-#define ACE_CFGLBA (0x0c)
>-#define ACE_MPULBA (0x10)
>-
>-#define ACE_SECCNTCMD (0x14)
>-#define ACE_SECCNTCMD_RESET      (0x0100)
>-#define ACE_SECCNTCMD_IDENTIFY   (0x0200)
>-#define ACE_SECCNTCMD_READ_DATA  (0x0300)
>-#define ACE_SECCNTCMD_WRITE_DATA (0x0400)
>-#define ACE_SECCNTCMD_ABORT      (0x0600)
>-
>-#define ACE_VERSION (0x16)
>-#define ACE_VERSION_REVISION_MASK (0x00FF)
>-#define ACE_VERSION_MINOR_MASK    (0x0F00)
>-#define ACE_VERSION_MAJOR_MASK    (0xF000)
>-
>-#define ACE_CTRL (0x18)
>-#define ACE_CTRL_FORCELOCKREQ   (0x0001)
>-#define ACE_CTRL_LOCKREQ        (0x0002)
>-#define ACE_CTRL_FORCECFGADDR   (0x0004)
>-#define ACE_CTRL_FORCECFGMODE   (0x0008)
>-#define ACE_CTRL_CFGMODE        (0x0010)
>-#define ACE_CTRL_CFGSTART       (0x0020)
>-#define ACE_CTRL_CFGSEL         (0x0040)
>-#define ACE_CTRL_CFGRESET       (0x0080)
>-#define ACE_CTRL_DATABUFRDYIRQ  (0x0100)
>-#define ACE_CTRL_ERRORIRQ       (0x0200)
>-#define ACE_CTRL_CFGDONEIRQ     (0x0400)
>-#define ACE_CTRL_RESETIRQ       (0x0800)
>-#define ACE_CTRL_CFGPROG        (0x1000)
>-#define ACE_CTRL_CFGADDR_MASK   (0xe000)
>-
>-#define ACE_FATSTAT (0x1c)
>-
>-#define ACE_NUM_MINORS 16
>-#define ACE_SECTOR_SIZE (512)
>-#define ACE_FIFO_SIZE (32)
>-#define ACE_BUF_PER_SECTOR (ACE_SECTOR_SIZE / ACE_FIFO_SIZE)
>-
>-#define ACE_BUS_WIDTH_8  0
>-#define ACE_BUS_WIDTH_16 1
>-
>-struct ace_reg_ops;
>-
>-struct ace_device {
>-	/* driver state data */
>-	int id;
>-	int media_change;
>-	int users;
>-	struct list_head list;
>-
>-	/* finite state machine data */
>-	struct tasklet_struct fsm_tasklet;
>-	uint fsm_task;		/* Current activity (ACE_TASK_*) */
>-	uint fsm_state;		/* Current state (ACE_FSM_STATE_*) */
>-	uint fsm_continue_flag;	/* cleared to exit FSM mainloop */
>-	uint fsm_iter_num;
>-	struct timer_list stall_timer;
>-
>-	/* Transfer state/result, use for both id and block request */
>-	struct request *req;	/* request being processed */
>-	void *data_ptr;		/* pointer to I/O buffer */
>-	int data_count;		/* number of buffers remaining */
>-	int data_result;	/* Result of transfer; 0 := success */
>-
>-	int id_req_count;	/* count of id requests */
>-	int id_result;
>-	struct completion id_completion;	/* used when id req finishes */
>-	int in_irq;
>-
>-	/* Details of hardware device */
>-	resource_size_t physaddr;
>-	void __iomem *baseaddr;
>-	int irq;
>-	int bus_width;		/* 0 := 8 bit; 1 := 16 bit */
>-	struct ace_reg_ops *reg_ops;
>-	int lock_count;
>-
>-	/* Block device data structures */
>-	spinlock_t lock;
>-	struct device *dev;
>-	struct request_queue *queue;
>-	struct gendisk *gd;
>-	struct blk_mq_tag_set tag_set;
>-	struct list_head rq_list;
>-
>-	/* Inserted CF card parameters */
>-	u16 cf_id[ATA_ID_WORDS];
>-};
>-
>-static DEFINE_MUTEX(xsysace_mutex);
>-static int ace_major;
>-
>-/* ---------------------------------------------------------------------
>- * Low level register access
>- */
>-
>-struct ace_reg_ops {
>-	u16(*in) (struct ace_device * ace, int reg);
>-	void (*out) (struct ace_device * ace, int reg, u16 val);
>-	void (*datain) (struct ace_device * ace);
>-	void (*dataout) (struct ace_device * ace);
>-};
>-
>-/* 8 Bit bus width */
>-static u16 ace_in_8(struct ace_device *ace, int reg)
>-{
>-	void __iomem *r = ace->baseaddr + reg;
>-	return in_8(r) | (in_8(r + 1) << 8);
>-}
>-
>-static void ace_out_8(struct ace_device *ace, int reg, u16 val)
>-{
>-	void __iomem *r = ace->baseaddr + reg;
>-	out_8(r, val);
>-	out_8(r + 1, val >> 8);
>-}
>-
>-static void ace_datain_8(struct ace_device *ace)
>-{
>-	void __iomem *r = ace->baseaddr + 0x40;
>-	u8 *dst = ace->data_ptr;
>-	int i = ACE_FIFO_SIZE;
>-	while (i--)
>-		*dst++ = in_8(r++);
>-	ace->data_ptr = dst;
>-}
>-
>-static void ace_dataout_8(struct ace_device *ace)
>-{
>-	void __iomem *r = ace->baseaddr + 0x40;
>-	u8 *src = ace->data_ptr;
>-	int i = ACE_FIFO_SIZE;
>-	while (i--)
>-		out_8(r++, *src++);
>-	ace->data_ptr = src;
>-}
>-
>-static struct ace_reg_ops ace_reg_8_ops = {
>-	.in = ace_in_8,
>-	.out = ace_out_8,
>-	.datain = ace_datain_8,
>-	.dataout = ace_dataout_8,
>-};
>-
>-/* 16 bit big endian bus attachment */
>-static u16 ace_in_be16(struct ace_device *ace, int reg)
>-{
>-	return in_be16(ace->baseaddr + reg);
>-}
>-
>-static void ace_out_be16(struct ace_device *ace, int reg, u16 val)
>-{
>-	out_be16(ace->baseaddr + reg, val);
>-}
>-
>-static void ace_datain_be16(struct ace_device *ace)
>-{
>-	int i = ACE_FIFO_SIZE / 2;
>-	u16 *dst = ace->data_ptr;
>-	while (i--)
>-		*dst++ = in_le16(ace->baseaddr + 0x40);
>-	ace->data_ptr = dst;
>-}
>-
>-static void ace_dataout_be16(struct ace_device *ace)
>-{
>-	int i = ACE_FIFO_SIZE / 2;
>-	u16 *src = ace->data_ptr;
>-	while (i--)
>-		out_le16(ace->baseaddr + 0x40, *src++);
>-	ace->data_ptr = src;
>-}
>-
>-/* 16 bit little endian bus attachment */
>-static u16 ace_in_le16(struct ace_device *ace, int reg)
>-{
>-	return in_le16(ace->baseaddr + reg);
>-}
>-
>-static void ace_out_le16(struct ace_device *ace, int reg, u16 val)
>-{
>-	out_le16(ace->baseaddr + reg, val);
>-}
>-
>-static void ace_datain_le16(struct ace_device *ace)
>-{
>-	int i = ACE_FIFO_SIZE / 2;
>-	u16 *dst = ace->data_ptr;
>-	while (i--)
>-		*dst++ = in_be16(ace->baseaddr + 0x40);
>-	ace->data_ptr = dst;
>-}
>-
>-static void ace_dataout_le16(struct ace_device *ace)
>-{
>-	int i = ACE_FIFO_SIZE / 2;
>-	u16 *src = ace->data_ptr;
>-	while (i--)
>-		out_be16(ace->baseaddr + 0x40, *src++);
>-	ace->data_ptr = src;
>-}
>-
>-static struct ace_reg_ops ace_reg_be16_ops = {
>-	.in = ace_in_be16,
>-	.out = ace_out_be16,
>-	.datain = ace_datain_be16,
>-	.dataout = ace_dataout_be16,
>-};
>-
>-static struct ace_reg_ops ace_reg_le16_ops = {
>-	.in = ace_in_le16,
>-	.out = ace_out_le16,
>-	.datain = ace_datain_le16,
>-	.dataout = ace_dataout_le16,
>-};
>-
>-static inline u16 ace_in(struct ace_device *ace, int reg)
>-{
>-	return ace->reg_ops->in(ace, reg);
>-}
>-
>-static inline u32 ace_in32(struct ace_device *ace, int reg)
>-{
>-	return ace_in(ace, reg) | (ace_in(ace, reg + 2) << 16);
>-}
>-
>-static inline void ace_out(struct ace_device *ace, int reg, u16 val)
>-{
>-	ace->reg_ops->out(ace, reg, val);
>-}
>-
>-static inline void ace_out32(struct ace_device *ace, int reg, u32 val)
>-{
>-	ace_out(ace, reg, val);
>-	ace_out(ace, reg + 2, val >> 16);
>-}
>-
>-/* ---------------------------------------------------------------------
>- * Debug support functions
>- */
>-
>-#if defined(DEBUG)
>-static void ace_dump_mem(void *base, int len)
>-{
>-	const char *ptr = base;
>-	int i, j;
>-
>-	for (i = 0; i < len; i += 16) {
>-		printk(KERN_INFO "%.8x:", i);
>-		for (j = 0; j < 16; j++) {
>-			if (!(j % 4))
>-				printk(" ");
>-			printk("%.2x", ptr[i + j]);
>-		}
>-		printk(" ");
>-		for (j = 0; j < 16; j++)
>-			printk("%c", isprint(ptr[i + j]) ? ptr[i + j] : '.');
>-		printk("\n");
>-	}
>-}
>-#else
>-static inline void ace_dump_mem(void *base, int len)
>-{
>-}
>-#endif
>-
>-static void ace_dump_regs(struct ace_device *ace)
>-{
>-	dev_info(ace->dev,
>-		 "    ctrl:  %.8x  seccnt/cmd: %.4x      ver:%.4x\n"
>-		 "    status:%.8x  mpu_lba:%.8x  busmode:%4x\n"
>-		 "    error: %.8x  cfg_lba:%.8x  fatstat:%.4x\n",
>-		 ace_in32(ace, ACE_CTRL),
>-		 ace_in(ace, ACE_SECCNTCMD),
>-		 ace_in(ace, ACE_VERSION),
>-		 ace_in32(ace, ACE_STATUS),
>-		 ace_in32(ace, ACE_MPULBA),
>-		 ace_in(ace, ACE_BUSMODE),
>-		 ace_in32(ace, ACE_ERROR),
>-		 ace_in32(ace, ACE_CFGLBA), ace_in(ace, ACE_FATSTAT));
>-}
>-
>-static void ace_fix_driveid(u16 *id)
>-{
>-#if defined(__BIG_ENDIAN)
>-	int i;
>-
>-	/* All half words have wrong byte order; swap the bytes */
>-	for (i = 0; i < ATA_ID_WORDS; i++, id++)
>-		*id = le16_to_cpu(*id);
>-#endif
>-}
>-
>-/* ---------------------------------------------------------------------
>- * Finite State Machine (FSM) implementation
>- */
>-
>-/* FSM tasks; used to direct state transitions */
>-#define ACE_TASK_IDLE      0
>-#define ACE_TASK_IDENTIFY  1
>-#define ACE_TASK_READ      2
>-#define ACE_TASK_WRITE     3
>-#define ACE_FSM_NUM_TASKS  4
>-
>-/* FSM state definitions */
>-#define ACE_FSM_STATE_IDLE               0
>-#define ACE_FSM_STATE_REQ_LOCK           1
>-#define ACE_FSM_STATE_WAIT_LOCK          2
>-#define ACE_FSM_STATE_WAIT_CFREADY       3
>-#define ACE_FSM_STATE_IDENTIFY_PREPARE   4
>-#define ACE_FSM_STATE_IDENTIFY_TRANSFER  5
>-#define ACE_FSM_STATE_IDENTIFY_COMPLETE  6
>-#define ACE_FSM_STATE_REQ_PREPARE        7
>-#define ACE_FSM_STATE_REQ_TRANSFER       8
>-#define ACE_FSM_STATE_REQ_COMPLETE       9
>-#define ACE_FSM_STATE_ERROR             10
>-#define ACE_FSM_NUM_STATES              11
>-
>-/* Set flag to exit FSM loop and reschedule tasklet */
>-static inline void ace_fsm_yieldpoll(struct ace_device *ace)
>-{
>-	tasklet_schedule(&ace->fsm_tasklet);
>-	ace->fsm_continue_flag = 0;
>-}
>-
>-static inline void ace_fsm_yield(struct ace_device *ace)
>-{
>-	dev_dbg(ace->dev, "%s()\n", __func__);
>-	ace_fsm_yieldpoll(ace);
>-}
>-
>-/* Set flag to exit FSM loop and wait for IRQ to reschedule tasklet */
>-static inline void ace_fsm_yieldirq(struct ace_device *ace)
>-{
>-	dev_dbg(ace->dev, "ace_fsm_yieldirq()\n");
>-
>-	if (ace->irq > 0)
>-		ace->fsm_continue_flag = 0;
>-	else
>-		ace_fsm_yieldpoll(ace);
>-}
>-
>-static bool ace_has_next_request(struct request_queue *q)
>-{
>-	struct ace_device *ace = q->queuedata;
>-
>-	return !list_empty(&ace->rq_list);
>-}
>-
>-/* Get the next read/write request; ending requests that we don't handle */
>-static struct request *ace_get_next_request(struct request_queue *q)
>-{
>-	struct ace_device *ace = q->queuedata;
>-	struct request *rq;
>-
>-	rq = list_first_entry_or_null(&ace->rq_list, struct request, queuelist);
>-	if (rq) {
>-		list_del_init(&rq->queuelist);
>-		blk_mq_start_request(rq);
>-	}
>-
>-	return NULL;
>-}
>-
>-static void ace_fsm_dostate(struct ace_device *ace)
>-{
>-	struct request *req;
>-	u32 status;
>-	u16 val;
>-	int count;
>-
>-#if defined(DEBUG)
>-	dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n",
>-		ace->fsm_state, ace->id_req_count);
>-#endif
>-
>-	/* Verify that there is actually a CF in the slot. If not, then
>-	 * bail out back to the idle state and wake up all the waiters */
>-	status = ace_in32(ace, ACE_STATUS);
>-	if ((status & ACE_STATUS_CFDETECT) == 0) {
>-		ace->fsm_state = ACE_FSM_STATE_IDLE;
>-		ace->media_change = 1;
>-		set_capacity(ace->gd, 0);
>-		dev_info(ace->dev, "No CF in slot\n");
>-
>-		/* Drop all in-flight and pending requests */
>-		if (ace->req) {
>-			blk_mq_end_request(ace->req, BLK_STS_IOERR);
>-			ace->req = NULL;
>-		}
>-		while ((req = ace_get_next_request(ace->queue)) != NULL)
>-			blk_mq_end_request(req, BLK_STS_IOERR);
>-
>-		/* Drop back to IDLE state and notify waiters */
>-		ace->fsm_state = ACE_FSM_STATE_IDLE;
>-		ace->id_result = -EIO;
>-		while (ace->id_req_count) {
>-			complete(&ace->id_completion);
>-			ace->id_req_count--;
>-		}
>-	}
>-
>-	switch (ace->fsm_state) {
>-	case ACE_FSM_STATE_IDLE:
>-		/* See if there is anything to do */
>-		if (ace->id_req_count || ace_has_next_request(ace->queue)) {
>-			ace->fsm_iter_num++;
>-			ace->fsm_state = ACE_FSM_STATE_REQ_LOCK;
>-			mod_timer(&ace->stall_timer, jiffies + HZ);
>-			if (!timer_pending(&ace->stall_timer))
>-				add_timer(&ace->stall_timer);
>-			break;
>-		}
>-		del_timer(&ace->stall_timer);
>-		ace->fsm_continue_flag = 0;
>-		break;
>-
>-	case ACE_FSM_STATE_REQ_LOCK:
>-		if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
>-			/* Already have the lock, jump to next state */
>-			ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
>-			break;
>-		}
>-
>-		/* Request the lock */
>-		val = ace_in(ace, ACE_CTRL);
>-		ace_out(ace, ACE_CTRL, val | ACE_CTRL_LOCKREQ);
>-		ace->fsm_state = ACE_FSM_STATE_WAIT_LOCK;
>-		break;
>-
>-	case ACE_FSM_STATE_WAIT_LOCK:
>-		if (ace_in(ace, ACE_STATUS) & ACE_STATUS_MPULOCK) {
>-			/* got the lock; move to next state */
>-			ace->fsm_state = ACE_FSM_STATE_WAIT_CFREADY;
>-			break;
>-		}
>-
>-		/* wait a bit for the lock */
>-		ace_fsm_yield(ace);
>-		break;
>-
>-	case ACE_FSM_STATE_WAIT_CFREADY:
>-		status = ace_in32(ace, ACE_STATUS);
>-		if (!(status & ACE_STATUS_RDYFORCFCMD) ||
>-		    (status & ACE_STATUS_CFBSY)) {
>-			/* CF card isn't ready; it needs to be polled */
>-			ace_fsm_yield(ace);
>-			break;
>-		}
>-
>-		/* Device is ready for command; determine what to do next */
>-		if (ace->id_req_count)
>-			ace->fsm_state = ACE_FSM_STATE_IDENTIFY_PREPARE;
>-		else
>-			ace->fsm_state = ACE_FSM_STATE_REQ_PREPARE;
>-		break;
>-
>-	case ACE_FSM_STATE_IDENTIFY_PREPARE:
>-		/* Send identify command */
>-		ace->fsm_task = ACE_TASK_IDENTIFY;
>-		ace->data_ptr = ace->cf_id;
>-		ace->data_count = ACE_BUF_PER_SECTOR;
>-		ace_out(ace, ACE_SECCNTCMD, ACE_SECCNTCMD_IDENTIFY);
>-
>-		/* As per datasheet, put config controller in reset */
>-		val = ace_in(ace, ACE_CTRL);
>-		ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
>-
>-		/* irq handler takes over from this point; wait for the
>-		 * transfer to complete */
>-		ace->fsm_state = ACE_FSM_STATE_IDENTIFY_TRANSFER;
>-		ace_fsm_yieldirq(ace);
>-		break;
>-
>-	case ACE_FSM_STATE_IDENTIFY_TRANSFER:
>-		/* Check that the sysace is ready to receive data */
>-		status = ace_in32(ace, ACE_STATUS);
>-		if (status & ACE_STATUS_CFBSY) {
>-			dev_dbg(ace->dev, "CFBSY set; t=%i iter=%i dc=%i\n",
>-				ace->fsm_task, ace->fsm_iter_num,
>-				ace->data_count);
>-			ace_fsm_yield(ace);
>-			break;
>-		}
>-		if (!(status & ACE_STATUS_DATABUFRDY)) {
>-			ace_fsm_yield(ace);
>-			break;
>-		}
>-
>-		/* Transfer the next buffer */
>-		ace->reg_ops->datain(ace);
>-		ace->data_count--;
>-
>-		/* If there are still buffers to be transfers; jump out here */
>-		if (ace->data_count != 0) {
>-			ace_fsm_yieldirq(ace);
>-			break;
>-		}
>-
>-		/* transfer finished; kick state machine */
>-		dev_dbg(ace->dev, "identify finished\n");
>-		ace->fsm_state = ACE_FSM_STATE_IDENTIFY_COMPLETE;
>-		break;
>-
>-	case ACE_FSM_STATE_IDENTIFY_COMPLETE:
>-		ace_fix_driveid(ace->cf_id);
>-		ace_dump_mem(ace->cf_id, 512);	/* Debug: Dump out disk ID */
>-
>-		if (ace->data_result) {
>-			/* Error occurred, disable the disk */
>-			ace->media_change = 1;
>-			set_capacity(ace->gd, 0);
>-			dev_err(ace->dev, "error fetching CF id (%i)\n",
>-				ace->data_result);
>-		} else {
>-			ace->media_change = 0;
>-
>-			/* Record disk parameters */
>-			set_capacity(ace->gd,
>-				ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY));
>-			dev_info(ace->dev, "capacity: %i sectors\n",
>-				ata_id_u32(ace->cf_id, ATA_ID_LBA_CAPACITY));
>-		}
>-
>-		/* We're done, drop to IDLE state and notify waiters */
>-		ace->fsm_state = ACE_FSM_STATE_IDLE;
>-		ace->id_result = ace->data_result;
>-		while (ace->id_req_count) {
>-			complete(&ace->id_completion);
>-			ace->id_req_count--;
>-		}
>-		break;
>-
>-	case ACE_FSM_STATE_REQ_PREPARE:
>-		req = ace_get_next_request(ace->queue);
>-		if (!req) {
>-			ace->fsm_state = ACE_FSM_STATE_IDLE;
>-			break;
>-		}
>-
>-		/* Okay, it's a data request, set it up for transfer */
>-		dev_dbg(ace->dev,
>-			"request: sec=%llx hcnt=%x, ccnt=%x, dir=%i\n",
>-			(unsigned long long)blk_rq_pos(req),
>-			blk_rq_sectors(req), blk_rq_cur_sectors(req),
>-			rq_data_dir(req));
>-
>-		ace->req = req;
>-		ace->data_ptr = bio_data(req->bio);
>-		ace->data_count = blk_rq_cur_sectors(req) * ACE_BUF_PER_SECTOR;
>-		ace_out32(ace, ACE_MPULBA, blk_rq_pos(req) & 0x0FFFFFFF);
>-
>-		count = blk_rq_sectors(req);
>-		if (rq_data_dir(req)) {
>-			/* Kick off write request */
>-			dev_dbg(ace->dev, "write data\n");
>-			ace->fsm_task = ACE_TASK_WRITE;
>-			ace_out(ace, ACE_SECCNTCMD,
>-				count | ACE_SECCNTCMD_WRITE_DATA);
>-		} else {
>-			/* Kick off read request */
>-			dev_dbg(ace->dev, "read data\n");
>-			ace->fsm_task = ACE_TASK_READ;
>-			ace_out(ace, ACE_SECCNTCMD,
>-				count | ACE_SECCNTCMD_READ_DATA);
>-		}
>-
>-		/* As per datasheet, put config controller in reset */
>-		val = ace_in(ace, ACE_CTRL);
>-		ace_out(ace, ACE_CTRL, val | ACE_CTRL_CFGRESET);
>-
>-		/* Move to the transfer state.  The systemace will raise
>-		 * an interrupt once there is something to do
>-		 */
>-		ace->fsm_state = ACE_FSM_STATE_REQ_TRANSFER;
>-		if (ace->fsm_task == ACE_TASK_READ)
>-			ace_fsm_yieldirq(ace);	/* wait for data ready */
>-		break;
>-
>-	case ACE_FSM_STATE_REQ_TRANSFER:
>-		/* Check that the sysace is ready to receive data */
>-		status = ace_in32(ace, ACE_STATUS);
>-		if (status & ACE_STATUS_CFBSY) {
>-			dev_dbg(ace->dev,
>-				"CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n",
>-				ace->fsm_task, ace->fsm_iter_num,
>-				blk_rq_cur_sectors(ace->req) * 16,
>-				ace->data_count, ace->in_irq);
>-			ace_fsm_yield(ace);	/* need to poll CFBSY bit */
>-			break;
>-		}
>-		if (!(status & ACE_STATUS_DATABUFRDY)) {
>-			dev_dbg(ace->dev,
>-				"DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n",
>-				ace->fsm_task, ace->fsm_iter_num,
>-				blk_rq_cur_sectors(ace->req) * 16,
>-				ace->data_count, ace->in_irq);
>-			ace_fsm_yieldirq(ace);
>-			break;
>-		}
>-
>-		/* Transfer the next buffer */
>-		if (ace->fsm_task == ACE_TASK_WRITE)
>-			ace->reg_ops->dataout(ace);
>-		else
>-			ace->reg_ops->datain(ace);
>-		ace->data_count--;
>-
>-		/* If there are still buffers to be transfers; jump out here */
>-		if (ace->data_count != 0) {
>-			ace_fsm_yieldirq(ace);
>-			break;
>-		}
>-
>-		/* bio finished; is there another one? */
>-		if (blk_update_request(ace->req, BLK_STS_OK,
>-		    blk_rq_cur_bytes(ace->req))) {
>-			/* dev_dbg(ace->dev, "next block; h=%u c=%u\n",
>-			 *      blk_rq_sectors(ace->req),
>-			 *      blk_rq_cur_sectors(ace->req));
>-			 */
>-			ace->data_ptr = bio_data(ace->req->bio);
>-			ace->data_count = blk_rq_cur_sectors(ace->req) * 16;
>-			ace_fsm_yieldirq(ace);
>-			break;
>-		}
>-
>-		ace->fsm_state = ACE_FSM_STATE_REQ_COMPLETE;
>-		break;
>-
>-	case ACE_FSM_STATE_REQ_COMPLETE:
>-		ace->req = NULL;
>-
>-		/* Finished request; go to idle state */
>-		ace->fsm_state = ACE_FSM_STATE_IDLE;
>-		break;
>-
>-	default:
>-		ace->fsm_state = ACE_FSM_STATE_IDLE;
>-		break;
>-	}
>-}
>-
>-static void ace_fsm_tasklet(unsigned long data)
>-{
>-	struct ace_device *ace = (void *)data;
>-	unsigned long flags;
>-
>-	spin_lock_irqsave(&ace->lock, flags);
>-
>-	/* Loop over state machine until told to stop */
>-	ace->fsm_continue_flag = 1;
>-	while (ace->fsm_continue_flag)
>-		ace_fsm_dostate(ace);
>-
>-	spin_unlock_irqrestore(&ace->lock, flags);
>-}
>-
>-static void ace_stall_timer(struct timer_list *t)
>-{
>-	struct ace_device *ace = from_timer(ace, t, stall_timer);
>-	unsigned long flags;
>-
>-	dev_warn(ace->dev,
>-		 "kicking stalled fsm; state=%i task=%i iter=%i dc=%i\n",
>-		 ace->fsm_state, ace->fsm_task, ace->fsm_iter_num,
>-		 ace->data_count);
>-	spin_lock_irqsave(&ace->lock, flags);
>-
>-	/* Rearm the stall timer *before* entering FSM (which may then
>-	 * delete the timer) */
>-	mod_timer(&ace->stall_timer, jiffies + HZ);
>-
>-	/* Loop over state machine until told to stop */
>-	ace->fsm_continue_flag = 1;
>-	while (ace->fsm_continue_flag)
>-		ace_fsm_dostate(ace);
>-
>-	spin_unlock_irqrestore(&ace->lock, flags);
>-}
>-
>-/* ---------------------------------------------------------------------
>- * Interrupt handling routines
>- */
>-static int ace_interrupt_checkstate(struct ace_device *ace)
>-{
>-	u32 sreg = ace_in32(ace, ACE_STATUS);
>-	u16 creg = ace_in(ace, ACE_CTRL);
>-
>-	/* Check for error occurrence */
>-	if ((sreg & (ACE_STATUS_CFGERROR | ACE_STATUS_CFCERROR)) &&
>-	    (creg & ACE_CTRL_ERRORIRQ)) {
>-		dev_err(ace->dev, "transfer failure\n");
>-		ace_dump_regs(ace);
>-		return -EIO;
>-	}
>-
>-	return 0;
>-}
>-
>-static irqreturn_t ace_interrupt(int irq, void *dev_id)
>-{
>-	u16 creg;
>-	struct ace_device *ace = dev_id;
>-
>-	/* be safe and get the lock */
>-	spin_lock(&ace->lock);
>-	ace->in_irq = 1;
>-
>-	/* clear the interrupt */
>-	creg = ace_in(ace, ACE_CTRL);
>-	ace_out(ace, ACE_CTRL, creg | ACE_CTRL_RESETIRQ);
>-	ace_out(ace, ACE_CTRL, creg);
>-
>-	/* check for IO failures */
>-	if (ace_interrupt_checkstate(ace))
>-		ace->data_result = -EIO;
>-
>-	if (ace->fsm_task == 0) {
>-		dev_err(ace->dev,
>-			"spurious irq; stat=%.8x ctrl=%.8x cmd=%.4x\n",
>-			ace_in32(ace, ACE_STATUS), ace_in32(ace, ACE_CTRL),
>-			ace_in(ace, ACE_SECCNTCMD));
>-		dev_err(ace->dev, "fsm_task=%i fsm_state=%i data_count=%i\n",
>-			ace->fsm_task, ace->fsm_state, ace->data_count);
>-	}
>-
>-	/* Loop over state machine until told to stop */
>-	ace->fsm_continue_flag = 1;
>-	while (ace->fsm_continue_flag)
>-		ace_fsm_dostate(ace);
>-
>-	/* done with interrupt; drop the lock */
>-	ace->in_irq = 0;
>-	spin_unlock(&ace->lock);
>-
>-	return IRQ_HANDLED;
>-}
>-
>-/* ---------------------------------------------------------------------
>- * Block ops
>- */
>-static blk_status_t ace_queue_rq(struct blk_mq_hw_ctx *hctx,
>-				 const struct blk_mq_queue_data *bd)
>-{
>-	struct ace_device *ace = hctx->queue->queuedata;
>-	struct request *req = bd->rq;
>-
>-	if (blk_rq_is_passthrough(req)) {
>-		blk_mq_start_request(req);
>-		return BLK_STS_IOERR;
>-	}
>-
>-	spin_lock_irq(&ace->lock);
>-	list_add_tail(&req->queuelist, &ace->rq_list);
>-	spin_unlock_irq(&ace->lock);
>-
>-	tasklet_schedule(&ace->fsm_tasklet);
>-	return BLK_STS_OK;
>-}
>-
>-static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
>-{
>-	struct ace_device *ace = gd->private_data;
>-	dev_dbg(ace->dev, "ace_check_events(): %i\n", ace->media_change);
>-
>-	return ace->media_change ? DISK_EVENT_MEDIA_CHANGE : 0;
>-}
>-
>-static void ace_media_changed(struct ace_device *ace)
>-{
>-	unsigned long flags;
>-
>-	dev_dbg(ace->dev, "requesting cf id and scheduling tasklet\n");
>-
>-	spin_lock_irqsave(&ace->lock, flags);
>-	ace->id_req_count++;
>-	spin_unlock_irqrestore(&ace->lock, flags);
>-
>-	tasklet_schedule(&ace->fsm_tasklet);
>-	wait_for_completion(&ace->id_completion);
>-
>-	dev_dbg(ace->dev, "revalidate complete\n");
>-}
>-
>-static int ace_open(struct block_device *bdev, fmode_t mode)
>-{
>-	struct ace_device *ace = bdev->bd_disk->private_data;
>-	unsigned long flags;
>-
>-	dev_dbg(ace->dev, "ace_open() users=%i\n", ace->users + 1);
>-
>-	mutex_lock(&xsysace_mutex);
>-	spin_lock_irqsave(&ace->lock, flags);
>-	ace->users++;
>-	spin_unlock_irqrestore(&ace->lock, flags);
>-
>-	if (bdev_check_media_change(bdev) && ace->media_change)
>-		ace_media_changed(ace);
>-	mutex_unlock(&xsysace_mutex);
>-
>-	return 0;
>-}
>-
>-static void ace_release(struct gendisk *disk, fmode_t mode)
>-{
>-	struct ace_device *ace = disk->private_data;
>-	unsigned long flags;
>-	u16 val;
>-
>-	dev_dbg(ace->dev, "ace_release() users=%i\n", ace->users - 1);
>-
>-	mutex_lock(&xsysace_mutex);
>-	spin_lock_irqsave(&ace->lock, flags);
>-	ace->users--;
>-	if (ace->users == 0) {
>-		val = ace_in(ace, ACE_CTRL);
>-		ace_out(ace, ACE_CTRL, val & ~ACE_CTRL_LOCKREQ);
>-	}
>-	spin_unlock_irqrestore(&ace->lock, flags);
>-	mutex_unlock(&xsysace_mutex);
>-}
>-
>-static int ace_getgeo(struct block_device *bdev, struct hd_geometry *geo)
>-{
>-	struct ace_device *ace = bdev->bd_disk->private_data;
>-	u16 *cf_id = ace->cf_id;
>-
>-	dev_dbg(ace->dev, "ace_getgeo()\n");
>-
>-	geo->heads	= cf_id[ATA_ID_HEADS];
>-	geo->sectors	= cf_id[ATA_ID_SECTORS];
>-	geo->cylinders	= cf_id[ATA_ID_CYLS];
>-
>-	return 0;
>-}
>-
>-static const struct block_device_operations ace_fops = {
>-	.owner = THIS_MODULE,
>-	.open = ace_open,
>-	.release = ace_release,
>-	.check_events = ace_check_events,
>-	.getgeo = ace_getgeo,
>-};
>-
>-static const struct blk_mq_ops ace_mq_ops = {
>-	.queue_rq	= ace_queue_rq,
>-};
>-
>-/* --------------------------------------------------------------------
>- * SystemACE device setup/teardown code
>- */
>-static int ace_setup(struct ace_device *ace)
>-{
>-	u16 version;
>-	u16 val;
>-	int rc;
>-
>-	dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace);
>-	dev_dbg(ace->dev, "physaddr=0x%llx irq=%i\n",
>-		(unsigned long long)ace->physaddr, ace->irq);
>-
>-	spin_lock_init(&ace->lock);
>-	init_completion(&ace->id_completion);
>-	INIT_LIST_HEAD(&ace->rq_list);
>-
>-	/*
>-	 * Map the device
>-	 */
>-	ace->baseaddr = ioremap(ace->physaddr, 0x80);
>-	if (!ace->baseaddr)
>-		goto err_ioremap;
>-
>-	/*
>-	 * Initialize the state machine tasklet and stall timer
>-	 */
>-	tasklet_init(&ace->fsm_tasklet, ace_fsm_tasklet, (unsigned long)ace);
>-	timer_setup(&ace->stall_timer, ace_stall_timer, 0);
>-
>-	/*
>-	 * Initialize the request queue
>-	 */
>-	ace->queue = blk_mq_init_sq_queue(&ace->tag_set, &ace_mq_ops, 2,
>-						BLK_MQ_F_SHOULD_MERGE);
>-	if (IS_ERR(ace->queue)) {
>-		rc = PTR_ERR(ace->queue);
>-		ace->queue = NULL;
>-		goto err_blk_initq;
>-	}
>-	ace->queue->queuedata = ace;
>-
>-	blk_queue_logical_block_size(ace->queue, 512);
>-	blk_queue_bounce_limit(ace->queue, BLK_BOUNCE_HIGH);
>-
>-	/*
>-	 * Allocate and initialize GD structure
>-	 */
>-	ace->gd = alloc_disk(ACE_NUM_MINORS);
>-	if (!ace->gd)
>-		goto err_alloc_disk;
>-
>-	ace->gd->major = ace_major;
>-	ace->gd->first_minor = ace->id * ACE_NUM_MINORS;
>-	ace->gd->fops = &ace_fops;
>-	ace->gd->events = DISK_EVENT_MEDIA_CHANGE;
>-	ace->gd->queue = ace->queue;
>-	ace->gd->private_data = ace;
>-	snprintf(ace->gd->disk_name, 32, "xs%c", ace->id + 'a');
>-
>-	/* set bus width */
>-	if (ace->bus_width == ACE_BUS_WIDTH_16) {
>-		/* 0x0101 should work regardless of endianess */
>-		ace_out_le16(ace, ACE_BUSMODE, 0x0101);
>-
>-		/* read it back to determine endianess */
>-		if (ace_in_le16(ace, ACE_BUSMODE) == 0x0001)
>-			ace->reg_ops = &ace_reg_le16_ops;
>-		else
>-			ace->reg_ops = &ace_reg_be16_ops;
>-	} else {
>-		ace_out_8(ace, ACE_BUSMODE, 0x00);
>-		ace->reg_ops = &ace_reg_8_ops;
>-	}
>-
>-	/* Make sure version register is sane */
>-	version = ace_in(ace, ACE_VERSION);
>-	if ((version == 0) || (version == 0xFFFF))
>-		goto err_read;
>-
>-	/* Put sysace in a sane state by clearing most control reg bits */
>-	ace_out(ace, ACE_CTRL, ACE_CTRL_FORCECFGMODE |
>-		ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ);
>-
>-	/* Now we can hook up the irq handler */
>-	if (ace->irq > 0) {
>-		rc = request_irq(ace->irq, ace_interrupt, 0, "systemace", ace);
>-		if (rc) {
>-			/* Failure - fall back to polled mode */
>-			dev_err(ace->dev, "request_irq failed\n");
>-			ace->irq = rc;
>-		}
>-	}
>-
>-	/* Enable interrupts */
>-	val = ace_in(ace, ACE_CTRL);
>-	val |= ACE_CTRL_DATABUFRDYIRQ | ACE_CTRL_ERRORIRQ;
>-	ace_out(ace, ACE_CTRL, val);
>-
>-	/* Print the identification */
>-	dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n",
>-		 (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff);
>-	dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n",
>-		(unsigned long long) ace->physaddr, ace->baseaddr, ace->irq);
>-
>-	ace->media_change = 1;
>-	ace_media_changed(ace);
>-
>-	/* Make the sysace device 'live' */
>-	add_disk(ace->gd);
>-
>-	return 0;
>-
>-err_read:
>-	/* prevent double queue cleanup */
>-	ace->gd->queue = NULL;
>-	put_disk(ace->gd);
>-err_alloc_disk:
>-	blk_cleanup_queue(ace->queue);
>-	blk_mq_free_tag_set(&ace->tag_set);
>-err_blk_initq:
>-	iounmap(ace->baseaddr);
>-err_ioremap:
>-	dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n",
>-		 (unsigned long long) ace->physaddr);
>-	return -ENOMEM;
>-}
>-
>-static void ace_teardown(struct ace_device *ace)
>-{
>-	if (ace->gd) {
>-		del_gendisk(ace->gd);
>-		put_disk(ace->gd);
>-	}
>-
>-	if (ace->queue) {
>-		blk_cleanup_queue(ace->queue);
>-		blk_mq_free_tag_set(&ace->tag_set);
>-	}
>-
>-	tasklet_kill(&ace->fsm_tasklet);
>-
>-	if (ace->irq > 0)
>-		free_irq(ace->irq, ace);
>-
>-	iounmap(ace->baseaddr);
>-}
>-
>-static int ace_alloc(struct device *dev, int id, resource_size_t physaddr,
>-		     int irq, int bus_width)
>-{
>-	struct ace_device *ace;
>-	int rc;
>-	dev_dbg(dev, "ace_alloc(%p)\n", dev);
>-
>-	/* Allocate and initialize the ace device structure */
>-	ace = kzalloc(sizeof(struct ace_device), GFP_KERNEL);
>-	if (!ace) {
>-		rc = -ENOMEM;
>-		goto err_alloc;
>-	}
>-
>-	ace->dev = dev;
>-	ace->id = id;
>-	ace->physaddr = physaddr;
>-	ace->irq = irq;
>-	ace->bus_width = bus_width;
>-
>-	/* Call the setup code */
>-	rc = ace_setup(ace);
>-	if (rc)
>-		goto err_setup;
>-
>-	dev_set_drvdata(dev, ace);
>-	return 0;
>-
>-err_setup:
>-	dev_set_drvdata(dev, NULL);
>-	kfree(ace);
>-err_alloc:
>-	dev_err(dev, "could not initialize device, err=%i\n", rc);
>-	return rc;
>-}
>-
>-static void ace_free(struct device *dev)
>-{
>-	struct ace_device *ace = dev_get_drvdata(dev);
>-	dev_dbg(dev, "ace_free(%p)\n", dev);
>-
>-	if (ace) {
>-		ace_teardown(ace);
>-		dev_set_drvdata(dev, NULL);
>-		kfree(ace);
>-	}
>-}
>-
>-/* ---------------------------------------------------------------------
>- * Platform Bus Support
>- */
>-
>-static int ace_probe(struct platform_device *dev)
>-{
>-	int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */
>-	resource_size_t physaddr;
>-	struct resource *res;
>-	u32 id = dev->id;
>-	int irq;
>-	int i;
>-
>-	dev_dbg(&dev->dev, "ace_probe(%p)\n", dev);
>-
>-	/* device id and bus width */
>-	if (of_property_read_u32(dev->dev.of_node, "port-number", &id))
>-		id = 0;
>-	if (of_find_property(dev->dev.of_node, "8-bit", NULL))
>-		bus_width = ACE_BUS_WIDTH_8;
>-
>-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
>-	if (!res)
>-		return -EINVAL;
>-
>-	physaddr = res->start;
>-	if (!physaddr)
>-		return -ENODEV;
>-
>-	irq = platform_get_irq_optional(dev, 0);
>-
>-	/* Call the bus-independent setup code */
>-	return ace_alloc(&dev->dev, id, physaddr, irq, bus_width);
>-}
>-
>-/*
>- * Platform bus remove() method
>- */
>-static int ace_remove(struct platform_device *dev)
>-{
>-	ace_free(&dev->dev);
>-	return 0;
>-}
>-
>-#if defined(CONFIG_OF)
>-/* Match table for of_platform binding */
>-static const struct of_device_id ace_of_match[] = {
>-	{ .compatible = "xlnx,opb-sysace-1.00.b", },
>-	{ .compatible = "xlnx,opb-sysace-1.00.c", },
>-	{ .compatible = "xlnx,xps-sysace-1.00.a", },
>-	{ .compatible = "xlnx,sysace", },
>-	{},
>-};
>-MODULE_DEVICE_TABLE(of, ace_of_match);
>-#else /* CONFIG_OF */
>-#define ace_of_match NULL
>-#endif /* CONFIG_OF */
>-
>-static struct platform_driver ace_platform_driver = {
>-	.probe = ace_probe,
>-	.remove = ace_remove,
>-	.driver = {
>-		.name = "xsysace",
>-		.of_match_table = ace_of_match,
>-	},
>-};
>-
>-/* ---------------------------------------------------------------------
>- * Module init/exit routines
>- */
>-static int __init ace_init(void)
>-{
>-	int rc;
>-
>-	ace_major = register_blkdev(ace_major, "xsysace");
>-	if (ace_major <= 0) {
>-		rc = -ENOMEM;
>-		goto err_blk;
>-	}
>-
>-	rc = platform_driver_register(&ace_platform_driver);
>-	if (rc)
>-		goto err_plat;
>-
>-	pr_info("Xilinx SystemACE device driver, major=%i\n", ace_major);
>-	return 0;
>-
>-err_plat:
>-	unregister_blkdev(ace_major, "xsysace");
>-err_blk:
>-	printk(KERN_ERR "xsysace: registration failed; err=%i\n", rc);
>-	return rc;
>-}
>-module_init(ace_init);
>-
>-static void __exit ace_exit(void)
>-{
>-	pr_debug("Unregistering Xilinx SystemACE driver\n");
>-	platform_driver_unregister(&ace_platform_driver);
>-	unregister_blkdev(ace_major, "xsysace");
>-}
>-module_exit(ace_exit);
>-- 
>2.29.2
>

^ permalink raw reply

* Re: [PATCH 02/10] ARM: disable CONFIG_IDE in footbridge_defconfig
From: Cye Borg @ 2021-03-22 15:44 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Jens Axboe, Thomas Bogendoerfer, linux-doc,
	Russell King - ARM Linux admin, linux-kernel, linux-ide,
	linux-m68k, Ivan Kokshaysky, linux-alpha, Geert Uytterhoeven,
	Matt Turner, linux-mips, linuxppc-dev, David S. Miller,
	linux-arm-kernel, Richard Henderson
In-Reply-To: <20210322151823.GA2764@lst.de>

[-- Attachment #1: Type: text/plain, Size: 1717 bytes --]

I use pata_cypress on Alpha, and for the above mentioned problems,
it always restricted me to use only one IDE channel out of the two
available. Also, not forcing it to use PIO mode, it always failed to
operate. I would love to test on Alpha, and give you feedback about
a fix/finished implementation of the driver. I have both Alpha Server DS20E
and Alpha Personal Workstation 500 including that freak chipset.

Let me know if/when I can help with my limited capabilities.

Thanks, best regards,
Barnabas Viragh

On Mon, Mar 22, 2021 at 4:19 PM Christoph Hellwig <hch@lst.de> wrote:

> On Mon, Mar 22, 2021 at 03:15:03PM +0000, Russell King - ARM Linux admin
> wrote:
> > It gets worse than that though - due to a change to remove
> > pcibios_min_io from the generic code, moving it into the ARM
> > architecture code, this has caused a regression that prevents the
> > legacy resources being registered against the bus resource. So even
> > if they are there, they cause probe failures. I haven't found a
> > reasonable way to solve this yet, but until there is, there is no
> > way that the PATA driver can be used as the "legacy mode" support
> > is effectively done via the PCI code assigning virtual IO port
> > resources.
> >
> > I'm quite surprised that the CY82C693 even works on Alpha - I've
> > asked for a lspci for that last week but nothing has yet been
> > forthcoming from whoever responded to your patch for Alpha - so I
> > can't compare what I'm seeing with what's happening with Alpha.
>
> That sounds like something we could fix with a quirk for function 2
> in the PCI resource assignment code.  Can you show what vendor and
> device ID function 2 has so that I could try to come up with one?
>

[-- Attachment #2: Type: text/html, Size: 2247 bytes --]

^ permalink raw reply

* Re: [PATCH 02/10] ARM: disable CONFIG_IDE in footbridge_defconfig
From: Cye Borg @ 2021-03-22 16:43 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz
  Cc: Jens Axboe, Thomas Bogendoerfer, linux-doc,
	Russell King - ARM Linux admin, Christoph Hellwig, linux-ide,
	linux-m68k, Geert Uytterhoeven, linux-arm-kernel, linux-alpha,
	Ivan Kokshaysky, Matt Turner, linux-mips, linuxppc-dev,
	David S. Miller, linux-kernel, Richard Henderson
In-Reply-To: <224b110e-7c42-4e19-800e-e0fa23d3bf7f@physik.fu-berlin.de>

[-- Attachment #1: Type: text/plain, Size: 2513 bytes --]

And lspci from Compaq PWS 500au:
snow / # lspci
00:03.0 Ethernet controller: Digital Equipment Corporation DECchip 21142/43
(rev 30)
00:07.0 ISA bridge: Contaq Microsystems 82c693
00:07.1 IDE interface: Contaq Microsystems 82c693
00:07.2 IDE interface: Contaq Microsystems 82c693
00:07.3 USB controller: Contaq Microsystems 82c693
00:0b.0 Multimedia video controller: 3Dfx Interactive, Inc. Voodoo 2 (rev
02)
00:0c.0 PCI bridge: Digital Equipment Corporation DECchip 21052 (rev 01)
00:14.0 PCI bridge: Digital Equipment Corporation DECchip 21152 (rev 02)
01:04.0 VGA compatible controller: Cirrus Logic GD 5430/40 [Alpine] (rev 47)
01:05.0 Display controller: Intergraph Corporation Device 00eb (rev 40)
02:04.0 SCSI storage controller: QLogic Corp. ISP1020 Fast-wide SCSI (rev
05)
02:0a.0 SCSI storage controller: Broadcom / LSI 53c810 (rev 01)

It's also using pata_cypress.

Barnabas Viragh

On Mon, Mar 22, 2021 at 5:10 PM John Paul Adrian Glaubitz <
glaubitz@physik.fu-berlin.de> wrote:

> On 3/22/21 4:15 PM, Russell King - ARM Linux admin wrote:
> > I'm quite surprised that the CY82C693 even works on Alpha - I've
> > asked for a lspci for that last week but nothing has yet been
> > forthcoming from whoever responded to your patch for Alpha - so I
> > can't compare what I'm seeing with what's happening with Alpha.
>
> Here is lspci on my DEC Alpha XP-1000:
>
> root@tsunami:~> lspci
> 0000:00:07.0 ISA bridge: Contaq Microsystems 82c693
> 0000:00:07.1 IDE interface: Contaq Microsystems 82c693
> 0000:00:07.2 IDE interface: Contaq Microsystems 82c693
> 0000:00:07.3 USB controller: Contaq Microsystems 82c693
> 0000:00:0d.0 VGA compatible controller: Texas Instruments TVP4020
> [Permedia 2] (rev 01)
> 0001:01:03.0 Ethernet controller: Digital Equipment Corporation DECchip
> 21142/43 (rev 41)
> 0001:01:06.0 SCSI storage controller: QLogic Corp. ISP1020 Fast-wide SCSI
> (rev 06)
> 0001:01:08.0 PCI bridge: Digital Equipment Corporation DECchip 21152 (rev
> 03)
> 0001:02:09.0 Ethernet controller: Intel Corporation 82541PI Gigabit
> Ethernet Controller (rev 05)
> root@tsunami:~>
>
> It's using pata_cypress:
>
> root@tsunami:~> lsmod|grep cypress
> pata_cypress            3595  3
> libata                235071  2 ata_generic,pata_cypress
> root@tsunami:~
>
> Adrian
>
> --
>  .''`.  John Paul Adrian Glaubitz
> : :' :  Debian Developer - glaubitz@debian.org
> `. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
>   `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913
>
>

[-- Attachment #2: Type: text/html, Size: 3223 bytes --]

^ permalink raw reply

* Re: [PATCH 02/10] ARM: disable CONFIG_IDE in footbridge_defconfig
From: Cye Borg @ 2021-03-22 16:47 UTC (permalink / raw)
  To: John Paul Adrian Glaubitz
  Cc: Jens Axboe, Thomas Bogendoerfer, linux-doc,
	Russell King - ARM Linux admin, Christoph Hellwig, linux-ide,
	linux-m68k, Geert Uytterhoeven, linux-arm-kernel, linux-alpha,
	Ivan Kokshaysky, Matt Turner, linux-mips, linuxppc-dev,
	David S. Miller, linux-kernel, Richard Henderson
In-Reply-To: <224b110e-7c42-4e19-800e-e0fa23d3bf7f@physik.fu-berlin.de>

I use pata_cypress on Alpha, and for the above mentioned problems,
it always restricted me to use only one IDE channel out of the two
available. Also, not forcing it to use PIO mode, it always failed to
operate. I would love to test on Alpha, and give you feedback about
a fix/finished implementation of the driver. I have both Alpha Server DS20E
and Alpha Personal Workstation 500 including that freak chipset.

Let me know if/when I can help with my limited capabilities.

btw, here is the lspci of the Compaq PWS 500au:
snow / # lspci
00:03.0 Ethernet controller: Digital Equipment Corporation DECchip
21142/43 (rev 30)
00:07.0 ISA bridge: Contaq Microsystems 82c693
00:07.1 IDE interface: Contaq Microsystems 82c693
00:07.2 IDE interface: Contaq Microsystems 82c693
00:07.3 USB controller: Contaq Microsystems 82c693
00:0b.0 Multimedia video controller: 3Dfx Interactive, Inc. Voodoo 2 (rev 02)
00:0c.0 PCI bridge: Digital Equipment Corporation DECchip 21052 (rev 01)
00:14.0 PCI bridge: Digital Equipment Corporation DECchip 21152 (rev 02)
01:04.0 VGA compatible controller: Cirrus Logic GD 5430/40 [Alpine] (rev 47)
01:05.0 Display controller: Intergraph Corporation Device 00eb (rev 40)
02:04.0 SCSI storage controller: QLogic Corp. ISP1020 Fast-wide SCSI (rev 05)
02:0a.0 SCSI storage controller: Broadcom / LSI 53c810 (rev 01)

Thanks, best regards,
Barnabas Viragh


On Mon, Mar 22, 2021 at 5:10 PM John Paul Adrian Glaubitz
<glaubitz@physik.fu-berlin.de> wrote:
>
> On 3/22/21 4:15 PM, Russell King - ARM Linux admin wrote:
> > I'm quite surprised that the CY82C693 even works on Alpha - I've
> > asked for a lspci for that last week but nothing has yet been
> > forthcoming from whoever responded to your patch for Alpha - so I
> > can't compare what I'm seeing with what's happening with Alpha.
>
> Here is lspci on my DEC Alpha XP-1000:
>
> root@tsunami:~> lspci
> 0000:00:07.0 ISA bridge: Contaq Microsystems 82c693
> 0000:00:07.1 IDE interface: Contaq Microsystems 82c693
> 0000:00:07.2 IDE interface: Contaq Microsystems 82c693
> 0000:00:07.3 USB controller: Contaq Microsystems 82c693
> 0000:00:0d.0 VGA compatible controller: Texas Instruments TVP4020 [Permedia 2] (rev 01)
> 0001:01:03.0 Ethernet controller: Digital Equipment Corporation DECchip 21142/43 (rev 41)
> 0001:01:06.0 SCSI storage controller: QLogic Corp. ISP1020 Fast-wide SCSI (rev 06)
> 0001:01:08.0 PCI bridge: Digital Equipment Corporation DECchip 21152 (rev 03)
> 0001:02:09.0 Ethernet controller: Intel Corporation 82541PI Gigabit Ethernet Controller (rev 05)
> root@tsunami:~>
>
> It's using pata_cypress:
>
> root@tsunami:~> lsmod|grep cypress
> pata_cypress            3595  3
> libata                235071  2 ata_generic,pata_cypress
> root@tsunami:~
>
> Adrian
>
> --
>  .''`.  John Paul Adrian Glaubitz
> : :' :  Debian Developer - glaubitz@debian.org
> `. `'   Freie Universitaet Berlin - glaubitz@physik.fu-berlin.de
>   `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913
>

^ permalink raw reply

* Re: [PATCH 02/10] ARM: disable CONFIG_IDE in footbridge_defconfig
From: Cye Borg @ 2021-03-22 17:10 UTC (permalink / raw)
  To: Russell King - ARM Linux admin
  Cc: Jens Axboe, Thomas Bogendoerfer, linux-doc, linux-alpha,
	linux-kernel, Christoph Hellwig, linux-ide, linux-m68k,
	Geert Uytterhoeven, John Paul Adrian Glaubitz, Ivan Kokshaysky,
	Matt Turner, linux-mips, linuxppc-dev, David S. Miller,
	linux-arm-kernel, Richard Henderson
In-Reply-To: <20210322170338.GZ1463@shell.armlinux.org.uk>

PWS 500au:

snow / # lspci -vvx -s 7.1
00:07.1 IDE interface: Contaq Microsystems 82c693 (prog-if 80 [ISA
Compatibility mode-only controller, supports bus mastering])
        Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop-
ParErr+ Stepping- SERR- FastB2B- DisINTx-
        Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium
>TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin A routed to IRQ 0
        Region 0: I/O ports at 01f0 [size=8]
        Region 1: I/O ports at 03f4
        Region 4: I/O ports at 9080 [size=16]
        Kernel driver in use: pata_cypress
        Kernel modules: pata_cypress
00: 80 10 93 c6 45 00 80 02 00 80 01 01 00 00 80 00
10: f1 01 00 00 f5 03 00 00 00 00 00 00 00 00 00 00
20: 81 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00

snow / # lspci -vvx -s 7.2
00:07.2 IDE interface: Contaq Microsystems 82c693 (prog-if 00 [ISA
Compatibility mode-only controller])
        Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop-
ParErr+ Stepping- SERR- FastB2B- DisINTx-
        Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium
>TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Latency: 0
        Interrupt: pin B routed to IRQ 0
        Region 0: I/O ports at 0170 [size=8]
        Region 1: I/O ports at 0374
        Region 4: Memory at 0c240000 (32-bit, non-prefetchable)
[disabled] [size=64K]
        Kernel modules: pata_cypress
00: 80 10 93 c6 45 00 80 02 00 00 01 01 00 00 80 00
10: 71 01 00 00 75 03 00 00 00 00 00 00 00 00 00 00
20: 00 00 24 0c 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00

On Mon, Mar 22, 2021 at 6:04 PM Russell King - ARM Linux admin
<linux@armlinux.org.uk> wrote:
>
> On Mon, Mar 22, 2021 at 05:09:13PM +0100, John Paul Adrian Glaubitz wrote:
> > On 3/22/21 4:15 PM, Russell King - ARM Linux admin wrote:
> > > I'm quite surprised that the CY82C693 even works on Alpha - I've
> > > asked for a lspci for that last week but nothing has yet been
> > > forthcoming from whoever responded to your patch for Alpha - so I
> > > can't compare what I'm seeing with what's happening with Alpha.
> >
> > Here is lspci on my DEC Alpha XP-1000:
> >
> > root@tsunami:~> lspci
> > 0000:00:07.0 ISA bridge: Contaq Microsystems 82c693
> > 0000:00:07.1 IDE interface: Contaq Microsystems 82c693
> > 0000:00:07.2 IDE interface: Contaq Microsystems 82c693
> > 0000:00:07.3 USB controller: Contaq Microsystems 82c693
> > 0000:00:0d.0 VGA compatible controller: Texas Instruments TVP4020 [Permedia 2] (rev 01)
> > 0001:01:03.0 Ethernet controller: Digital Equipment Corporation DECchip 21142/43 (rev 41)
> > 0001:01:06.0 SCSI storage controller: QLogic Corp. ISP1020 Fast-wide SCSI (rev 06)
> > 0001:01:08.0 PCI bridge: Digital Equipment Corporation DECchip 21152 (rev 03)
> > 0001:02:09.0 Ethernet controller: Intel Corporation 82541PI Gigabit Ethernet Controller (rev 05)
> > root@tsunami:~>
>
> This is no good. What I asked last Thursday was:
>
> "Could you send me the output of lspci -vvx -s 7.1 and lspci -vvx -s 7.2
> please?"
>
> so I can see the resources the kernel is using and a dump of the PCI
> config space to see what the hardware is using.
>
> Thanks.
>
> --
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply

* [PATCH v4 00/46] KVM: PPC: Book3S: C-ify the P9 entry/exit code
From: Nicholas Piggin @ 2021-03-23  1:02 UTC (permalink / raw)
  To: kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin

I think enough changes and fixes have gone in since last round
to repost.

I put a git tree here to make things easier to get.

https://github.com/npiggin/linux/tree/kvm-in-c-2

Main changes since v3:
- Hopefully fixed LPCR sanising [from Fabiano review]
- Added MSR[HV] clearing of guest MSR (like MSR[ME] setting).
- Restored a lost comment about PPR saving, improved comments a bit
  [Daniel review]
- Added isyncs, removed XXX isync comment.
- Fixed cede comment [Fabiano]
- In stop handling real mode handlers patch, fixed problem of nested
  hcall handler calling cede and xics hcalls and consuming them
  [Fabiano]
- Filter xics hcalls from being consumed if !kvmppc_xics_enabled
  [Fabiano, Alexey noticed and Cedric provided the right recipe and
   comment]
- Removed some more of radix, nested, and virt mode paths from the
  P7/8 code [noticed by Alexey].
- Rebased on 5.12-rc4
- Hopefully I responded to all reviews and collected all reviewed-bys.

Thanks,
Nick

Nicholas Piggin (46):
  KVM: PPC: Book3S HV: Nested move LPCR sanitising to sanitise_hv_regs
  KVM: PPC: Book3S HV: Add a function to filter guest LPCR bits
  KVM: PPC: Book3S HV: Disallow LPCR[AIL] to be set to 1 or 2
  KVM: PPC: Book3S HV: Prevent radix guests from setting LPCR[TC]
  KVM: PPC: Book3S HV: Remove redundant mtspr PSPB
  KVM: PPC: Book3S HV: remove unused kvmppc_h_protect argument
  KVM: PPC: Book3S HV: Fix CONFIG_SPAPR_TCE_IOMMU=n default hcalls
  powerpc/64s: Remove KVM handler support from CBE_RAS interrupts
  powerpc/64s: remove KVM SKIP test from instruction breakpoint handler
  KVM: PPC: Book3S HV: Ensure MSR[ME] is always set in guest MSR
  KVM: PPC: Book3S HV: Ensure MSR[HV] is always clear in guest MSR
  KVM: PPC: Book3S 64: move KVM interrupt entry to a common entry point
  KVM: PPC: Book3S 64: Move GUEST_MODE_SKIP test into KVM
  KVM: PPC: Book3S 64: add hcall interrupt handler
  KVM: PPC: Book3S 64: Move hcall early register setup to KVM
  KVM: PPC: Book3S 64: Move interrupt early register setup to KVM
  KVM: PPC: Book3S 64: move bad_host_intr check to HV handler
  KVM: PPC: Book3S 64: Minimise hcall handler calling convention
    differences
  KVM: PPC: Book3S HV P9: Move radix MMU switching instructions together
  KVM: PPC: Book3S HV P9: implement kvmppc_xive_pull_vcpu in C
  KVM: PPC: Book3S HV P9: Move xive vcpu context management into
    kvmhv_p9_guest_entry
  KVM: PPC: Book3S HV P9: Stop handling hcalls in real-mode in the P9
    path
  KVM: PPC: Book3S HV P9: Move setting HDEC after switching to guest
    LPCR
  KVM: PPC: Book3S HV P9: Use large decrementer for HDEC
  KVM: PPC: Book3S HV P9: Use host timer accounting to avoid decrementer
    read
  KVM: PPC: Book3S HV P9: Reduce mftb per guest entry/exit
  powerpc: add set_dec_or_work API for safely updating decrementer
  KVM: PPC: Book3S HV P9: Reduce irq_work vs guest decrementer races
  KVM: PPC: Book3S HV P9: Implement the rest of the P9 path in C
  KVM: PPC: Book3S HV P9: inline kvmhv_load_hv_regs_and_go into
    __kvmhv_vcpu_entry_p9
  KVM: PPC: Book3S HV P9: Read machine check registers while MSR[RI] is
    0
  KVM: PPC: Book3S HV P9: Improve exit timing accounting coverage
  KVM: PPC: Book3S HV P9: Move SPR loading after expiry time check
  KVM: PPC: Book3S HV P9: Add helpers for OS SPR handling
  KVM: PPC: Book3S HV P9: Switch to guest MMU context as late as
    possible
  KVM: PPC: Book3S HV: Implement radix prefetch workaround by disabling
    MMU
  KVM: PPC: Book3S HV: Remove support for dependent threads mode on P9
  KVM: PPC: Book3S HV: Remove radix guest support from P7/8 path
  KVM: PPC: Book3S HV: Remove virt mode checks from real mode handlers
  KVM: PPC: Book3S HV: Remove unused nested HV tests in XICS emulation
  KVM: PPC: Book3S HV P9: Allow all P9 processors to enable nested HV
  KVM: PPC: Book3S HV: small pseries_do_hcall cleanup
  KVM: PPC: Book3S HV: add virtual mode handlers for HPT hcalls and page
    faults
  KVM: PPC: Book3S HV P9: implement hash guest support
  KVM: PPC: Book3S HV P9: implement hash host / hash guest support
  KVM: PPC: Book3S HV: remove ISA v3.0 and v3.1 support from P7/8 path

 arch/powerpc/include/asm/asm-prototypes.h |   3 +-
 arch/powerpc/include/asm/exception-64s.h  |  13 +
 arch/powerpc/include/asm/kvm_asm.h        |   3 +-
 arch/powerpc/include/asm/kvm_book3s.h     |   2 +
 arch/powerpc/include/asm/kvm_book3s_64.h  |   8 +
 arch/powerpc/include/asm/kvm_host.h       |   1 -
 arch/powerpc/include/asm/kvm_ppc.h        |  20 +-
 arch/powerpc/include/asm/mmu_context.h    |   6 -
 arch/powerpc/include/asm/time.h           |  16 +
 arch/powerpc/kernel/exceptions-64s.S      | 257 ++------
 arch/powerpc/kernel/security.c            |   5 +-
 arch/powerpc/kernel/time.c                |  21 +-
 arch/powerpc/kvm/Makefile                 |   6 +
 arch/powerpc/kvm/book3s.c                 |  11 +-
 arch/powerpc/kvm/book3s_64_entry.S        | 394 ++++++++++++
 arch/powerpc/kvm/book3s_64_vio_hv.c       |  12 -
 arch/powerpc/kvm/book3s_hv.c              | 730 ++++++++++++----------
 arch/powerpc/kvm/book3s_hv_builtin.c      | 138 +---
 arch/powerpc/kvm/book3s_hv_interrupt.c    | 528 ++++++++++++++++
 arch/powerpc/kvm/book3s_hv_interrupts.S   |   9 +-
 arch/powerpc/kvm/book3s_hv_nested.c       |  22 +-
 arch/powerpc/kvm/book3s_hv_ras.c          |   2 +
 arch/powerpc/kvm/book3s_hv_rm_mmu.c       |  15 +-
 arch/powerpc/kvm/book3s_hv_rm_xics.c      |  15 -
 arch/powerpc/kvm/book3s_hv_rmhandlers.S   | 641 +------------------
 arch/powerpc/kvm/book3s_segment.S         |   7 +
 arch/powerpc/kvm/book3s_xive.c            | 119 +++-
 arch/powerpc/kvm/book3s_xive.h            |   7 -
 arch/powerpc/kvm/book3s_xive_native.c     |  10 -
 arch/powerpc/mm/book3s64/radix_pgtable.c  |  27 +-
 arch/powerpc/mm/book3s64/radix_tlb.c      |  46 --
 arch/powerpc/mm/mmu_context.c             |   4 +-
 arch/powerpc/platforms/powernv/idle.c     |  52 +-
 33 files changed, 1632 insertions(+), 1518 deletions(-)
 create mode 100644 arch/powerpc/kvm/book3s_64_entry.S
 create mode 100644 arch/powerpc/kvm/book3s_hv_interrupt.c

-- 
2.23.0


^ permalink raw reply

* [PATCH v4 01/46] KVM: PPC: Book3S HV: Nested move LPCR sanitising to sanitise_hv_regs
From: Nicholas Piggin @ 2021-03-23  1:02 UTC (permalink / raw)
  To: kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>

This will get a bit more complicated in future patches. Move it
into the helper function.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kvm/book3s_hv_nested.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 0cd0e7aad588..2fe1fea4c934 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -134,6 +134,16 @@ static void save_hv_return_state(struct kvm_vcpu *vcpu, int trap,
 
 static void sanitise_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
 {
+	struct kvmppc_vcore *vc = vcpu->arch.vcore;
+	u64 mask;
+
+	/*
+	 * Don't let L1 change LPCR bits for the L2 except these:
+	 */
+	mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD |
+		LPCR_LPES | LPCR_MER;
+	hr->lpcr = (vc->lpcr & ~mask) | (hr->lpcr & mask);
+
 	/*
 	 * Don't let L1 enable features for L2 which we've disabled for L1,
 	 * but preserve the interrupt cause field.
@@ -271,8 +281,6 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
 	u64 hv_ptr, regs_ptr;
 	u64 hdec_exp;
 	s64 delta_purr, delta_spurr, delta_ic, delta_vtb;
-	u64 mask;
-	unsigned long lpcr;
 
 	if (vcpu->kvm->arch.l1_ptcr == 0)
 		return H_NOT_AVAILABLE;
@@ -321,9 +329,7 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
 	vcpu->arch.nested_vcpu_id = l2_hv.vcpu_token;
 	vcpu->arch.regs = l2_regs;
 	vcpu->arch.shregs.msr = vcpu->arch.regs.msr;
-	mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD |
-		LPCR_LPES | LPCR_MER;
-	lpcr = (vc->lpcr & ~mask) | (l2_hv.lpcr & mask);
+
 	sanitise_hv_regs(vcpu, &l2_hv);
 	restore_hv_regs(vcpu, &l2_hv);
 
@@ -335,7 +341,7 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
 			r = RESUME_HOST;
 			break;
 		}
-		r = kvmhv_run_single_vcpu(vcpu, hdec_exp, lpcr);
+		r = kvmhv_run_single_vcpu(vcpu, hdec_exp, l2_hv.lpcr);
 	} while (is_kvmppc_resume_guest(r));
 
 	/* save L2 state for return */
-- 
2.23.0


^ permalink raw reply related

* [PATCH v4 02/46] KVM: PPC: Book3S HV: Add a function to filter guest LPCR bits
From: Nicholas Piggin @ 2021-03-23  1:02 UTC (permalink / raw)
  To: kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>

Guest LPCR depends on hardware type, and future changes will add
restrictions based on errata and guest MMU mode. Move this logic
to a common function and use it for the cases where the guest
wants to update its LPCR (or the LPCR of a nested guest).

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/kvm_book3s.h |  2 +
 arch/powerpc/kvm/book3s_hv.c          | 60 ++++++++++++++++++---------
 arch/powerpc/kvm/book3s_hv_nested.c   |  3 +-
 3 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 2f5f919f6cd3..3eec3ef6f083 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -258,6 +258,8 @@ extern long kvmppc_hv_get_dirty_log_hpt(struct kvm *kvm,
 extern void kvmppc_harvest_vpa_dirty(struct kvmppc_vpa *vpa,
 			struct kvm_memory_slot *memslot,
 			unsigned long *map);
+extern unsigned long kvmppc_filter_lpcr_hv(struct kvmppc_vcore *vc,
+			unsigned long lpcr);
 extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr,
 			unsigned long mask);
 extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr);
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 13bad6bf4c95..c4539c38c639 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1635,6 +1635,27 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu,
 	return 0;
 }
 
+/*
+ * Enforce limits on guest LPCR values based on hardware availability,
+ * guest configuration, and possibly hypervisor support and security
+ * concerns.
+ */
+unsigned long kvmppc_filter_lpcr_hv(struct kvmppc_vcore *vc, unsigned long lpcr)
+{
+	/* On POWER8 and above, userspace can modify AIL */
+	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+		lpcr &= ~LPCR_AIL;
+
+	/*
+	 * On POWER9, allow userspace to enable large decrementer for the
+	 * guest, whether or not the host has it enabled.
+	 */
+	if (!cpu_has_feature(CPU_FTR_ARCH_300))
+		lpcr &= ~LPCR_LD;
+
+	return lpcr;
+}
+
 static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
 		bool preserve_top32)
 {
@@ -1643,6 +1664,23 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
 	u64 mask;
 
 	spin_lock(&vc->lock);
+
+	/*
+	 * Userspace can only modify
+	 * DPFD (default prefetch depth), ILE (interrupt little-endian),
+	 * TC (translation control), AIL (alternate interrupt location),
+	 * LD (large decrementer).
+	 * These are subject to restrictions from kvmppc_filter_lcpr_hv().
+	 */
+	mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD;
+
+	/* Broken 32-bit version of LPCR must not clear top bits */
+	if (preserve_top32)
+		mask &= 0xFFFFFFFF;
+
+	new_lpcr = kvmppc_filter_lpcr_hv(vc,
+			(vc->lpcr & ~mask) | (new_lpcr & mask));
+
 	/*
 	 * If ILE (interrupt little-endian) has changed, update the
 	 * MSR_LE bit in the intr_msr for each vcpu in this vcore.
@@ -1661,25 +1699,8 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr,
 		}
 	}
 
-	/*
-	 * Userspace can only modify DPFD (default prefetch depth),
-	 * ILE (interrupt little-endian) and TC (translation control).
-	 * On POWER8 and POWER9 userspace can also modify AIL (alt. interrupt loc.).
-	 */
-	mask = LPCR_DPFD | LPCR_ILE | LPCR_TC;
-	if (cpu_has_feature(CPU_FTR_ARCH_207S))
-		mask |= LPCR_AIL;
-	/*
-	 * On POWER9, allow userspace to enable large decrementer for the
-	 * guest, whether or not the host has it enabled.
-	 */
-	if (cpu_has_feature(CPU_FTR_ARCH_300))
-		mask |= LPCR_LD;
+	vc->lpcr = new_lpcr;
 
-	/* Broken 32-bit version of LPCR must not clear top bits */
-	if (preserve_top32)
-		mask &= 0xFFFFFFFF;
-	vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask);
 	spin_unlock(&vc->lock);
 }
 
@@ -4641,8 +4662,9 @@ void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask)
 		struct kvmppc_vcore *vc = kvm->arch.vcores[i];
 		if (!vc)
 			continue;
+
 		spin_lock(&vc->lock);
-		vc->lpcr = (vc->lpcr & ~mask) | lpcr;
+		vc->lpcr = kvmppc_filter_lpcr_hv(vc, (vc->lpcr & ~mask) | lpcr);
 		spin_unlock(&vc->lock);
 		if (++cores_done >= kvm->arch.online_vcores)
 			break;
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 2fe1fea4c934..f7b441b3eb17 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -142,7 +142,8 @@ static void sanitise_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
 	 */
 	mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD |
 		LPCR_LPES | LPCR_MER;
-	hr->lpcr = (vc->lpcr & ~mask) | (hr->lpcr & mask);
+	hr->lpcr = kvmppc_filter_lpcr_hv(vc,
+			(vc->lpcr & ~mask) | (hr->lpcr & mask));
 
 	/*
 	 * Don't let L1 enable features for L2 which we've disabled for L1,
-- 
2.23.0


^ permalink raw reply related

* [PATCH v4 03/46] KVM: PPC: Book3S HV: Disallow LPCR[AIL] to be set to 1 or 2
From: Nicholas Piggin @ 2021-03-23  1:02 UTC (permalink / raw)
  To: kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin, Fabiano Rosas
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>

These are already disallowed by H_SET_MODE from the guest, also disallow
these by updating LPCR directly.

AIL modes can affect the host interrupt behaviour while the guest LPCR
value is set, so filter it here too.

Suggested-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kvm/book3s_hv.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c4539c38c639..c5de7e3f22b6 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -803,7 +803,10 @@ static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags,
 		vcpu->arch.dawrx1 = value2;
 		return H_SUCCESS;
 	case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE:
-		/* KVM does not support mflags=2 (AIL=2) */
+		/*
+		 * KVM does not support mflags=2 (AIL=2) and AIL=1 is reserved.
+		 * Keep this in synch with kvmppc_filter_guest_lpcr_hv.
+		 */
 		if (mflags != 0 && mflags != 3)
 			return H_UNSUPPORTED_FLAG_START;
 		return H_TOO_HARD;
@@ -1645,6 +1648,8 @@ unsigned long kvmppc_filter_lpcr_hv(struct kvmppc_vcore *vc, unsigned long lpcr)
 	/* On POWER8 and above, userspace can modify AIL */
 	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
 		lpcr &= ~LPCR_AIL;
+	if ((lpcr & LPCR_AIL) != LPCR_AIL_3)
+		lpcr &= ~LPCR_AIL; /* LPCR[AIL]=1/2 is disallowed */
 
 	/*
 	 * On POWER9, allow userspace to enable large decrementer for the
-- 
2.23.0


^ permalink raw reply related

* [PATCH v4 04/46] KVM: PPC: Book3S HV: Prevent radix guests from setting LPCR[TC]
From: Nicholas Piggin @ 2021-03-23  1:02 UTC (permalink / raw)
  To: kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>

This bit only applies to hash partitions.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kvm/book3s_hv.c        | 6 ++++++
 arch/powerpc/kvm/book3s_hv_nested.c | 3 +--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c5de7e3f22b6..1ffb0902e779 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1645,6 +1645,12 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu,
  */
 unsigned long kvmppc_filter_lpcr_hv(struct kvmppc_vcore *vc, unsigned long lpcr)
 {
+	struct kvm *kvm = vc->kvm;
+
+	/* LPCR_TC only applies to HPT guests */
+	if (kvm_is_radix(kvm))
+		lpcr &= ~LPCR_TC;
+
 	/* On POWER8 and above, userspace can modify AIL */
 	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
 		lpcr &= ~LPCR_AIL;
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index f7b441b3eb17..851e3f527eb2 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -140,8 +140,7 @@ static void sanitise_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr)
 	/*
 	 * Don't let L1 change LPCR bits for the L2 except these:
 	 */
-	mask = LPCR_DPFD | LPCR_ILE | LPCR_TC | LPCR_AIL | LPCR_LD |
-		LPCR_LPES | LPCR_MER;
+	mask = LPCR_DPFD | LPCR_ILE | LPCR_AIL | LPCR_LD | LPCR_LPES | LPCR_MER;
 	hr->lpcr = kvmppc_filter_lpcr_hv(vc,
 			(vc->lpcr & ~mask) | (hr->lpcr & mask));
 
-- 
2.23.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox