* 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
* [PATCH v4 05/46] KVM: PPC: Book3S HV: Remove redundant mtspr PSPB
From: Nicholas Piggin @ 2021-03-23 1:02 UTC (permalink / raw)
To: kvm-ppc; +Cc: Daniel Axtens, linuxppc-dev, Nicholas Piggin, Fabiano Rosas
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>
This SPR is set to 0 twice when exiting the guest.
Suggested-by: Fabiano Rosas <farosas@linux.ibm.com>
Reviewed-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kvm/book3s_hv.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 1ffb0902e779..7cfaabab2c20 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -3781,7 +3781,6 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
mtspr(SPRN_DSCR, host_dscr);
mtspr(SPRN_TIDR, host_tidr);
mtspr(SPRN_IAMR, host_iamr);
- mtspr(SPRN_PSPB, 0);
if (host_amr != vcpu->arch.amr)
mtspr(SPRN_AMR, host_amr);
--
2.23.0
^ permalink raw reply related
* [PATCH v4 06/46] KVM: PPC: Book3S HV: remove unused kvmppc_h_protect argument
From: Nicholas Piggin @ 2021-03-23 1:02 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin, Daniel Axtens
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>
The va argument is not used in the function or set by its asm caller,
so remove it to be safe.
Reviewed-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/kvm_ppc.h | 3 +--
arch/powerpc/kvm/book3s_hv_rm_mmu.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 8aacd76bb702..9531b1c1b190 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -767,8 +767,7 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
unsigned long pte_index, unsigned long avpn);
long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu);
long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
- unsigned long pte_index, unsigned long avpn,
- unsigned long va);
+ unsigned long pte_index, unsigned long avpn);
long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
unsigned long pte_index);
long kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags,
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 88da2764c1bb..7af7c70f1468 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -673,8 +673,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
}
long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
- unsigned long pte_index, unsigned long avpn,
- unsigned long va)
+ unsigned long pte_index, unsigned long avpn)
{
struct kvm *kvm = vcpu->kvm;
__be64 *hpte;
--
2.23.0
^ permalink raw reply related
* [PATCH v4 07/46] KVM: PPC: Book3S HV: Fix CONFIG_SPAPR_TCE_IOMMU=n default hcalls
From: Nicholas Piggin @ 2021-03-23 1:02 UTC (permalink / raw)
To: kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin, Daniel Axtens
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>
This config option causes the warning in init_default_hcalls to fire
because the TCE handlers are in the default hcall list but not
implemented.
Reviewed-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kvm/book3s_hv.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 7cfaabab2c20..7bb4222729b0 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -5401,8 +5401,10 @@ static unsigned int default_hcall_list[] = {
H_READ,
H_PROTECT,
H_BULK_REMOVE,
+#ifdef CONFIG_SPAPR_TCE_IOMMU
H_GET_TCE,
H_PUT_TCE,
+#endif
H_SET_DABR,
H_SET_XDABR,
H_CEDE,
--
2.23.0
^ permalink raw reply related
* [PATCH v4 08/46] powerpc/64s: Remove KVM handler support from CBE_RAS interrupts
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>
Cell does not support KVM.
Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 8082b690e874..a0515cb829c2 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -2530,8 +2530,6 @@ EXC_VIRT_NONE(0x5100, 0x100)
INT_DEFINE_BEGIN(cbe_system_error)
IVEC=0x1200
IHSRR=1
- IKVM_SKIP=1
- IKVM_REAL=1
INT_DEFINE_END(cbe_system_error)
EXC_REAL_BEGIN(cbe_system_error, 0x1200, 0x100)
@@ -2701,8 +2699,6 @@ EXC_COMMON_BEGIN(denorm_exception_common)
INT_DEFINE_BEGIN(cbe_maintenance)
IVEC=0x1600
IHSRR=1
- IKVM_SKIP=1
- IKVM_REAL=1
INT_DEFINE_END(cbe_maintenance)
EXC_REAL_BEGIN(cbe_maintenance, 0x1600, 0x100)
@@ -2754,8 +2750,6 @@ EXC_COMMON_BEGIN(altivec_assist_common)
INT_DEFINE_BEGIN(cbe_thermal)
IVEC=0x1800
IHSRR=1
- IKVM_SKIP=1
- IKVM_REAL=1
INT_DEFINE_END(cbe_thermal)
EXC_REAL_BEGIN(cbe_thermal, 0x1800, 0x100)
--
2.23.0
^ permalink raw reply related
* [PATCH v4 09/46] powerpc/64s: remove KVM SKIP test from instruction breakpoint handler
From: Nicholas Piggin @ 2021-03-23 1:02 UTC (permalink / raw)
To: kvm-ppc; +Cc: Fabiano Rosas, linuxppc-dev, Nicholas Piggin, Daniel Axtens
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>
The code being executed in KVM_GUEST_MODE_SKIP is hypervisor code with
MSR[IR]=0, so the faults of concern are the d-side ones caused by access
to guest context by the hypervisor.
Instruction breakpoint interrupts are not a concern here. It's unlikely
any good would come of causing breaks in this code, but skipping the
instruction that caused it won't help matters (e.g., skip the mtmsr that
sets MSR[DR]=0 or clears KVM_GUEST_MODE_SKIP).
Reviewed-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index a0515cb829c2..c9c446ccff54 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -2553,7 +2553,6 @@ EXC_VIRT_NONE(0x5200, 0x100)
INT_DEFINE_BEGIN(instruction_breakpoint)
IVEC=0x1300
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
- IKVM_SKIP=1
IKVM_REAL=1
#endif
INT_DEFINE_END(instruction_breakpoint)
--
2.23.0
^ permalink raw reply related
* [PATCH v4 10/46] KVM: PPC: Book3S HV: Ensure MSR[ME] is always set in guest MSR
From: Nicholas Piggin @ 2021-03-23 1:02 UTC (permalink / raw)
To: kvm-ppc; +Cc: Fabiano Rosas, linuxppc-dev, Nicholas Piggin, Daniel Axtens
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>
Rather than add the ME bit to the MSR at guest entry, make it clear
that the hypervisor does not allow the guest to clear the bit.
The ME set is kept in guest entry for now, but a future patch will
warn if it's not present.
Reviewed-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kvm/book3s_hv_builtin.c | 3 +++
arch/powerpc/kvm/book3s_hv_nested.c | 4 +++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 158d309b42a3..41cb03d0bde4 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -662,6 +662,9 @@ static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
{
+ /* Guest must always run with ME enabled. */
+ msr = msr | MSR_ME;
+
/*
* Check for illegal transactional state bit combination
* and if we find it, force the TS field to a safe state.
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 851e3f527eb2..886c7fa86add 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -328,7 +328,9 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
vcpu->arch.nested = l2;
vcpu->arch.nested_vcpu_id = l2_hv.vcpu_token;
vcpu->arch.regs = l2_regs;
- vcpu->arch.shregs.msr = vcpu->arch.regs.msr;
+
+ /* Guest must always run with ME enabled. */
+ vcpu->arch.shregs.msr = vcpu->arch.regs.msr | MSR_ME;
sanitise_hv_regs(vcpu, &l2_hv);
restore_hv_regs(vcpu, &l2_hv);
--
2.23.0
^ permalink raw reply related
* [PATCH v4 11/46] KVM: PPC: Book3S HV: Ensure MSR[HV] is always clear in guest MSR
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>
Rather than clear the HV bit from the MSR at guest entry, make it clear
that the hypervisor does not allow the guest to set the bit.
The HV clear is kept in guest entry for now, but a future patch will
warn if it's not present.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kvm/book3s_hv_builtin.c | 4 ++--
arch/powerpc/kvm/book3s_hv_nested.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 41cb03d0bde4..7a0e33a9c980 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -662,8 +662,8 @@ static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
{
- /* Guest must always run with ME enabled. */
- msr = msr | MSR_ME;
+ /* Guest must always run with ME enabled, HV disabled. */
+ msr = (msr | MSR_ME) & ~MSR_HV;
/*
* Check for illegal transactional state bit combination
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 886c7fa86add..d192e799c0af 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -329,8 +329,8 @@ long kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu)
vcpu->arch.nested_vcpu_id = l2_hv.vcpu_token;
vcpu->arch.regs = l2_regs;
- /* Guest must always run with ME enabled. */
- vcpu->arch.shregs.msr = vcpu->arch.regs.msr | MSR_ME;
+ /* Guest must always run with ME enabled, HV disabled. */
+ vcpu->arch.shregs.msr = (vcpu->arch.regs.msr | MSR_ME) & ~MSR_HV;
sanitise_hv_regs(vcpu, &l2_hv);
restore_hv_regs(vcpu, &l2_hv);
--
2.23.0
^ permalink raw reply related
* [PATCH v4 12/46] KVM: PPC: Book3S 64: move KVM interrupt entry to a common entry point
From: Nicholas Piggin @ 2021-03-23 1:02 UTC (permalink / raw)
To: kvm-ppc; +Cc: Fabiano Rosas, linuxppc-dev, Nicholas Piggin, Daniel Axtens
In-Reply-To: <20210323010305.1045293-1-npiggin@gmail.com>
Rather than bifurcate the call depending on whether or not HV is
possible, and have the HV entry test for PR, just make a single
common point which does the demultiplexing. This makes it simpler
to add another type of exit handler.
Reviewed-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Fabiano Rosas <farosas@linux.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/kernel/exceptions-64s.S | 8 +-----
arch/powerpc/kvm/Makefile | 3 +++
arch/powerpc/kvm/book3s_64_entry.S | 36 +++++++++++++++++++++++++
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 11 ++------
4 files changed, 42 insertions(+), 16 deletions(-)
create mode 100644 arch/powerpc/kvm/book3s_64_entry.S
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index c9c446ccff54..162595af1ac7 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -208,7 +208,6 @@ do_define_int n
.endm
#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
/*
* All interrupts which set HSRR registers, as well as SRESET and MCE and
* syscall when invoked with "sc 1" switch to MSR[HV]=1 (HVMODE) to be taken,
@@ -238,13 +237,8 @@ do_define_int n
/*
* If an interrupt is taken while a guest is running, it is immediately routed
- * to KVM to handle. If both HV and PR KVM arepossible, KVM interrupts go first
- * to kvmppc_interrupt_hv, which handles the PR guest case.
+ * to KVM to handle.
*/
-#define kvmppc_interrupt kvmppc_interrupt_hv
-#else
-#define kvmppc_interrupt kvmppc_interrupt_pr
-#endif
.macro KVMTEST name
lbz r10,HSTATE_IN_GUEST(r13)
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 2bfeaa13befb..cdd119028f64 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -59,6 +59,9 @@ kvm-pr-y := \
kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
tm.o
+kvm-book3s_64-builtin-objs-y += \
+ book3s_64_entry.o
+
ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
book3s_rmhandlers.o
diff --git a/arch/powerpc/kvm/book3s_64_entry.S b/arch/powerpc/kvm/book3s_64_entry.S
new file mode 100644
index 000000000000..7a039ea78f15
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_64_entry.S
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <asm/asm-offsets.h>
+#include <asm/cache.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_book3s_asm.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+
+/*
+ * This is branched to from interrupt handlers in exception-64s.S which set
+ * IKVM_REAL or IKVM_VIRT, if HSTATE_IN_GUEST was found to be non-zero.
+ */
+.global kvmppc_interrupt
+.balign IFETCH_ALIGN_BYTES
+kvmppc_interrupt:
+ /*
+ * Register contents:
+ * R12 = (guest CR << 32) | interrupt vector
+ * R13 = PACA
+ * guest R12 saved in shadow VCPU SCRATCH0
+ * guest R13 saved in SPRN_SCRATCH0
+ */
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ std r9,HSTATE_SCRATCH2(r13)
+ lbz r9,HSTATE_IN_GUEST(r13)
+ cmpwi r9,KVM_GUEST_MODE_HOST_HV
+ beq kvmppc_bad_host_intr
+#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
+ cmpwi r9,KVM_GUEST_MODE_GUEST
+ ld r9,HSTATE_SCRATCH2(r13)
+ beq kvmppc_interrupt_pr
+#endif
+ b kvmppc_interrupt_hv
+#else
+ b kvmppc_interrupt_pr
+#endif
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 5e634db4809b..f976efb7e4a9 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1269,16 +1269,8 @@ kvmppc_interrupt_hv:
* R13 = PACA
* guest R12 saved in shadow VCPU SCRATCH0
* guest R13 saved in SPRN_SCRATCH0
+ * guest R9 saved in HSTATE_SCRATCH2
*/
- std r9, HSTATE_SCRATCH2(r13)
- lbz r9, HSTATE_IN_GUEST(r13)
- cmpwi r9, KVM_GUEST_MODE_HOST_HV
- beq kvmppc_bad_host_intr
-#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
- cmpwi r9, KVM_GUEST_MODE_GUEST
- ld r9, HSTATE_SCRATCH2(r13)
- beq kvmppc_interrupt_pr
-#endif
/* We're now back in the host but in guest MMU context */
li r9, KVM_GUEST_MODE_HOST_HV
stb r9, HSTATE_IN_GUEST(r13)
@@ -3280,6 +3272,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST)
* cfar is saved in HSTATE_CFAR(r13)
* ppr is saved in HSTATE_PPR(r13)
*/
+.global kvmppc_bad_host_intr
kvmppc_bad_host_intr:
/*
* Switch to the emergency stack, but start half-way down in
--
2.23.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox