* [PATCH 01/32] docs/vm: active_mm.txt convert to ReST format
From: Mike Rapoport @ 2018-03-21 19:22 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Andrey Ryabinin, Richard Henderson, Ivan Kokshaysky, Matt Turner,
Tony Luck, Fenghua Yu, Ralf Baechle, James Hogan,
Michael Ellerman, Alexander Viro, linux-kernel, linux-doc,
kasan-dev, linux-alpha, linux-ia64, linux-mips, linuxppc-dev,
linux-fsdevel, linux-mm, Mike Rapoport
In-Reply-To: <1521660168-14372-1-git-send-email-rppt@linux.vnet.ibm.com>
Just add a label for cross-referencing and indent the text to make it
``literal``
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
---
Documentation/vm/active_mm.txt | 174 +++++++++++++++++++++--------------------
1 file changed, 91 insertions(+), 83 deletions(-)
diff --git a/Documentation/vm/active_mm.txt b/Documentation/vm/active_mm.txt
index dbf4581..c84471b 100644
--- a/Documentation/vm/active_mm.txt
+++ b/Documentation/vm/active_mm.txt
@@ -1,83 +1,91 @@
-List: linux-kernel
-Subject: Re: active_mm
-From: Linus Torvalds <torvalds () transmeta ! com>
-Date: 1999-07-30 21:36:24
-
-Cc'd to linux-kernel, because I don't write explanations all that often,
-and when I do I feel better about more people reading them.
-
-On Fri, 30 Jul 1999, David Mosberger wrote:
->
-> Is there a brief description someplace on how "mm" vs. "active_mm" in
-> the task_struct are supposed to be used? (My apologies if this was
-> discussed on the mailing lists---I just returned from vacation and
-> wasn't able to follow linux-kernel for a while).
-
-Basically, the new setup is:
-
- - we have "real address spaces" and "anonymous address spaces". The
- difference is that an anonymous address space doesn't care about the
- user-level page tables at all, so when we do a context switch into an
- anonymous address space we just leave the previous address space
- active.
-
- The obvious use for a "anonymous address space" is any thread that
- doesn't need any user mappings - all kernel threads basically fall into
- this category, but even "real" threads can temporarily say that for
- some amount of time they are not going to be interested in user space,
- and that the scheduler might as well try to avoid wasting time on
- switching the VM state around. Currently only the old-style bdflush
- sync does that.
-
- - "tsk->mm" points to the "real address space". For an anonymous process,
- tsk->mm will be NULL, for the logical reason that an anonymous process
- really doesn't _have_ a real address space at all.
-
- - however, we obviously need to keep track of which address space we
- "stole" for such an anonymous user. For that, we have "tsk->active_mm",
- which shows what the currently active address space is.
-
- The rule is that for a process with a real address space (ie tsk->mm is
- non-NULL) the active_mm obviously always has to be the same as the real
- one.
-
- For a anonymous process, tsk->mm == NULL, and tsk->active_mm is the
- "borrowed" mm while the anonymous process is running. When the
- anonymous process gets scheduled away, the borrowed address space is
- returned and cleared.
-
-To support all that, the "struct mm_struct" now has two counters: a
-"mm_users" counter that is how many "real address space users" there are,
-and a "mm_count" counter that is the number of "lazy" users (ie anonymous
-users) plus one if there are any real users.
-
-Usually there is at least one real user, but it could be that the real
-user exited on another CPU while a lazy user was still active, so you do
-actually get cases where you have a address space that is _only_ used by
-lazy users. That is often a short-lived state, because once that thread
-gets scheduled away in favour of a real thread, the "zombie" mm gets
-released because "mm_users" becomes zero.
-
-Also, a new rule is that _nobody_ ever has "init_mm" as a real MM any
-more. "init_mm" should be considered just a "lazy context when no other
-context is available", and in fact it is mainly used just at bootup when
-no real VM has yet been created. So code that used to check
-
- if (current->mm == &init_mm)
-
-should generally just do
-
- if (!current->mm)
-
-instead (which makes more sense anyway - the test is basically one of "do
-we have a user context", and is generally done by the page fault handler
-and things like that).
-
-Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago,
-because it slightly changes the interfaces to accommodate the alpha (who
-would have thought it, but the alpha actually ends up having one of the
-ugliest context switch codes - unlike the other architectures where the MM
-and register state is separate, the alpha PALcode joins the two, and you
-need to switch both together).
-
-(From http://marc.info/?l=linux-kernel&m=93337278602211&w=2)
+.. _active_mm:
+
+=========
+Active MM
+=========
+
+::
+
+ List: linux-kernel
+ Subject: Re: active_mm
+ From: Linus Torvalds <torvalds () transmeta ! com>
+ Date: 1999-07-30 21:36:24
+
+ Cc'd to linux-kernel, because I don't write explanations all that often,
+ and when I do I feel better about more people reading them.
+
+ On Fri, 30 Jul 1999, David Mosberger wrote:
+ >
+ > Is there a brief description someplace on how "mm" vs. "active_mm" in
+ > the task_struct are supposed to be used? (My apologies if this was
+ > discussed on the mailing lists---I just returned from vacation and
+ > wasn't able to follow linux-kernel for a while).
+
+ Basically, the new setup is:
+
+ - we have "real address spaces" and "anonymous address spaces". The
+ difference is that an anonymous address space doesn't care about the
+ user-level page tables at all, so when we do a context switch into an
+ anonymous address space we just leave the previous address space
+ active.
+
+ The obvious use for a "anonymous address space" is any thread that
+ doesn't need any user mappings - all kernel threads basically fall into
+ this category, but even "real" threads can temporarily say that for
+ some amount of time they are not going to be interested in user space,
+ and that the scheduler might as well try to avoid wasting time on
+ switching the VM state around. Currently only the old-style bdflush
+ sync does that.
+
+ - "tsk->mm" points to the "real address space". For an anonymous process,
+ tsk->mm will be NULL, for the logical reason that an anonymous process
+ really doesn't _have_ a real address space at all.
+
+ - however, we obviously need to keep track of which address space we
+ "stole" for such an anonymous user. For that, we have "tsk->active_mm",
+ which shows what the currently active address space is.
+
+ The rule is that for a process with a real address space (ie tsk->mm is
+ non-NULL) the active_mm obviously always has to be the same as the real
+ one.
+
+ For a anonymous process, tsk->mm == NULL, and tsk->active_mm is the
+ "borrowed" mm while the anonymous process is running. When the
+ anonymous process gets scheduled away, the borrowed address space is
+ returned and cleared.
+
+ To support all that, the "struct mm_struct" now has two counters: a
+ "mm_users" counter that is how many "real address space users" there are,
+ and a "mm_count" counter that is the number of "lazy" users (ie anonymous
+ users) plus one if there are any real users.
+
+ Usually there is at least one real user, but it could be that the real
+ user exited on another CPU while a lazy user was still active, so you do
+ actually get cases where you have a address space that is _only_ used by
+ lazy users. That is often a short-lived state, because once that thread
+ gets scheduled away in favour of a real thread, the "zombie" mm gets
+ released because "mm_users" becomes zero.
+
+ Also, a new rule is that _nobody_ ever has "init_mm" as a real MM any
+ more. "init_mm" should be considered just a "lazy context when no other
+ context is available", and in fact it is mainly used just at bootup when
+ no real VM has yet been created. So code that used to check
+
+ if (current->mm == &init_mm)
+
+ should generally just do
+
+ if (!current->mm)
+
+ instead (which makes more sense anyway - the test is basically one of "do
+ we have a user context", and is generally done by the page fault handler
+ and things like that).
+
+ Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago,
+ because it slightly changes the interfaces to accommodate the alpha (who
+ would have thought it, but the alpha actually ends up having one of the
+ ugliest context switch codes - unlike the other architectures where the MM
+ and register state is separate, the alpha PALcode joins the two, and you
+ need to switch both together).
+
+ (From http://marc.info/?l=linux-kernel&m=93337278602211&w=2)
--
2.7.4
^ permalink raw reply related
* [PATCH 00/32] docs/vm: convert to ReST format
From: Mike Rapoport @ 2018-03-21 19:22 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Andrey Ryabinin, Richard Henderson, Ivan Kokshaysky, Matt Turner,
Tony Luck, Fenghua Yu, Ralf Baechle, James Hogan,
Michael Ellerman, Alexander Viro, linux-kernel, linux-doc,
kasan-dev, linux-alpha, linux-ia64, linux-mips, linuxppc-dev,
linux-fsdevel, linux-mm, Mike Rapoport
Hi,
These patches convert files in Documentation/vm to ReST format, add an
initial index and link it to the top level documentation.
There are no contents changes in the documentation, except few spelling
fixes. The relatively large diffstat stems from the indentation and
paragraph wrapping changes.
I've tried to keep the formatting as consistent as possible, but I could
miss some places that needed markup and add some markup where it was not
necessary.
Mike Rapoport (32):
docs/vm: active_mm.txt convert to ReST format
docs/vm: balance: convert to ReST format
docs/vm: cleancache.txt: convert to ReST format
docs/vm: frontswap.txt: convert to ReST format
docs/vm: highmem.txt: convert to ReST format
docs/vm: hmm.txt: convert to ReST format
docs/vm: hugetlbpage.txt: convert to ReST format
docs/vm: hugetlbfs_reserv.txt: convert to ReST format
docs/vm: hwpoison.txt: convert to ReST format
docs/vm: idle_page_tracking.txt: convert to ReST format
docs/vm: ksm.txt: convert to ReST format
docs/vm: mmu_notifier.txt: convert to ReST format
docs/vm: numa_memory_policy.txt: convert to ReST format
docs/vm: overcommit-accounting: convert to ReST format
docs/vm: page_frags convert to ReST format
docs/vm: numa: convert to ReST format
docs/vm: pagemap.txt: convert to ReST format
docs/vm: page_migration: convert to ReST format
docs/vm: page_owner: convert to ReST format
docs/vm: remap_file_pages.txt: conert to ReST format
docs/vm: slub.txt: convert to ReST format
docs/vm: soft-dirty.txt: convert to ReST format
docs/vm: split_page_table_lock: convert to ReST format
docs/vm: swap_numa.txt: convert to ReST format
docs/vm: transhuge.txt: convert to ReST format
docs/vm: unevictable-lru.txt: convert to ReST format
docs/vm: userfaultfd.txt: convert to ReST format
docs/vm: z3fold.txt: convert to ReST format
docs/vm: zsmalloc.txt: convert to ReST format
docs/vm: zswap.txt: convert to ReST format
docs/vm: rename documentation files to .rst
docs/vm: add index.rst and link MM documentation to top level index
Documentation/ABI/stable/sysfs-devices-node | 2 +-
.../ABI/testing/sysfs-kernel-mm-hugepages | 2 +-
Documentation/ABI/testing/sysfs-kernel-mm-ksm | 2 +-
Documentation/ABI/testing/sysfs-kernel-slab | 4 +-
Documentation/admin-guide/kernel-parameters.txt | 12 +-
Documentation/dev-tools/kasan.rst | 2 +-
Documentation/filesystems/proc.txt | 4 +-
Documentation/filesystems/tmpfs.txt | 2 +-
Documentation/index.rst | 3 +-
Documentation/sysctl/vm.txt | 6 +-
Documentation/vm/00-INDEX | 58 +--
Documentation/vm/active_mm.rst | 91 ++++
Documentation/vm/active_mm.txt | 83 ----
Documentation/vm/{balance => balance.rst} | 15 +-
.../vm/{cleancache.txt => cleancache.rst} | 105 +++--
Documentation/vm/conf.py | 10 +
Documentation/vm/{frontswap.txt => frontswap.rst} | 59 ++-
Documentation/vm/{highmem.txt => highmem.rst} | 87 ++--
Documentation/vm/{hmm.txt => hmm.rst} | 66 ++-
.../{hugetlbfs_reserv.txt => hugetlbfs_reserv.rst} | 212 +++++----
.../vm/{hugetlbpage.txt => hugetlbpage.rst} | 243 ++++++-----
Documentation/vm/{hwpoison.txt => hwpoison.rst} | 141 +++---
...le_page_tracking.txt => idle_page_tracking.rst} | 55 ++-
Documentation/vm/index.rst | 56 +++
Documentation/vm/ksm.rst | 183 ++++++++
Documentation/vm/ksm.txt | 178 --------
Documentation/vm/mmu_notifier.rst | 99 +++++
Documentation/vm/mmu_notifier.txt | 93 ----
Documentation/vm/{numa => numa.rst} | 6 +-
Documentation/vm/numa_memory_policy.rst | 485 +++++++++++++++++++++
Documentation/vm/numa_memory_policy.txt | 452 -------------------
Documentation/vm/overcommit-accounting | 80 ----
Documentation/vm/overcommit-accounting.rst | 87 ++++
Documentation/vm/{page_frags => page_frags.rst} | 5 +-
.../vm/{page_migration => page_migration.rst} | 149 ++++---
.../vm/{page_owner.txt => page_owner.rst} | 34 +-
Documentation/vm/{pagemap.txt => pagemap.rst} | 170 ++++----
.../{remap_file_pages.txt => remap_file_pages.rst} | 6 +
Documentation/vm/slub.rst | 361 +++++++++++++++
Documentation/vm/slub.txt | 342 ---------------
.../vm/{soft-dirty.txt => soft-dirty.rst} | 20 +-
...t_page_table_lock => split_page_table_lock.rst} | 12 +-
Documentation/vm/{swap_numa.txt => swap_numa.rst} | 55 ++-
Documentation/vm/{transhuge.txt => transhuge.rst} | 286 +++++++-----
.../{unevictable-lru.txt => unevictable-lru.rst} | 117 +++--
.../vm/{userfaultfd.txt => userfaultfd.rst} | 66 +--
Documentation/vm/{z3fold.txt => z3fold.rst} | 6 +-
Documentation/vm/{zsmalloc.txt => zsmalloc.rst} | 60 ++-
Documentation/vm/{zswap.txt => zswap.rst} | 71 +--
MAINTAINERS | 2 +-
arch/alpha/Kconfig | 2 +-
arch/ia64/Kconfig | 2 +-
arch/mips/Kconfig | 2 +-
arch/powerpc/Kconfig | 2 +-
fs/Kconfig | 2 +-
fs/dax.c | 2 +-
fs/proc/task_mmu.c | 4 +-
include/linux/hmm.h | 2 +-
include/linux/memremap.h | 4 +-
include/linux/mmu_notifier.h | 2 +-
include/linux/sched/mm.h | 4 +-
include/linux/swap.h | 2 +-
mm/Kconfig | 6 +-
mm/cleancache.c | 2 +-
mm/frontswap.c | 2 +-
mm/hmm.c | 2 +-
mm/huge_memory.c | 4 +-
mm/hugetlb.c | 4 +-
mm/ksm.c | 4 +-
mm/mmap.c | 2 +-
mm/rmap.c | 6 +-
mm/util.c | 2 +-
72 files changed, 2604 insertions(+), 2205 deletions(-)
create mode 100644 Documentation/vm/active_mm.rst
delete mode 100644 Documentation/vm/active_mm.txt
rename Documentation/vm/{balance => balance.rst} (96%)
rename Documentation/vm/{cleancache.txt => cleancache.rst} (83%)
create mode 100644 Documentation/vm/conf.py
rename Documentation/vm/{frontswap.txt => frontswap.rst} (91%)
rename Documentation/vm/{highmem.txt => highmem.rst} (64%)
rename Documentation/vm/{hmm.txt => hmm.rst} (92%)
rename Documentation/vm/{hugetlbfs_reserv.txt => hugetlbfs_reserv.rst} (87%)
rename Documentation/vm/{hugetlbpage.txt => hugetlbpage.rst} (64%)
rename Documentation/vm/{hwpoison.txt => hwpoison.rst} (60%)
rename Documentation/vm/{idle_page_tracking.txt => idle_page_tracking.rst} (72%)
create mode 100644 Documentation/vm/index.rst
create mode 100644 Documentation/vm/ksm.rst
delete mode 100644 Documentation/vm/ksm.txt
create mode 100644 Documentation/vm/mmu_notifier.rst
delete mode 100644 Documentation/vm/mmu_notifier.txt
rename Documentation/vm/{numa => numa.rst} (99%)
create mode 100644 Documentation/vm/numa_memory_policy.rst
delete mode 100644 Documentation/vm/numa_memory_policy.txt
delete mode 100644 Documentation/vm/overcommit-accounting
create mode 100644 Documentation/vm/overcommit-accounting.rst
rename Documentation/vm/{page_frags => page_frags.rst} (97%)
rename Documentation/vm/{page_migration => page_migration.rst} (63%)
rename Documentation/vm/{page_owner.txt => page_owner.rst} (86%)
rename Documentation/vm/{pagemap.txt => pagemap.rst} (60%)
rename Documentation/vm/{remap_file_pages.txt => remap_file_pages.rst} (92%)
create mode 100644 Documentation/vm/slub.rst
delete mode 100644 Documentation/vm/slub.txt
rename Documentation/vm/{soft-dirty.txt => soft-dirty.rst} (67%)
rename Documentation/vm/{split_page_table_lock => split_page_table_lock.rst} (95%)
rename Documentation/vm/{swap_numa.txt => swap_numa.rst} (74%)
rename Documentation/vm/{transhuge.txt => transhuge.rst} (74%)
rename Documentation/vm/{unevictable-lru.txt => unevictable-lru.rst} (92%)
rename Documentation/vm/{userfaultfd.txt => userfaultfd.rst} (89%)
rename Documentation/vm/{z3fold.txt => z3fold.rst} (97%)
rename Documentation/vm/{zsmalloc.txt => zsmalloc.rst} (71%)
rename Documentation/vm/{zswap.txt => zswap.rst} (74%)
--
2.7.4
^ permalink raw reply
* Re: [PATCH v2 5/5] powerpc64/ftrace: Implement support for ftrace_regs_caller()
From: Naveen N. Rao @ 2018-03-21 19:10 UTC (permalink / raw)
To: Steven Rostedt
Cc: Anton Blanchard, linuxppc-dev, Michael Ellerman, Nicholas Piggin,
Paul Mackerras, sathnaga
In-Reply-To: <20180321113142.7291ded1@gandalf.local.home>
Steven Rostedt wrote:
> On Wed, 21 Mar 2018 20:59:03 +0530
> "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
>=20
>> Thanks for the review!
>=20
> You're welcome. Note, I did put "Acked-by" and not "Reviewed-by"
> because my "Reviewed-by" is usually a bit more thorough than what I did
> for your patches. That's because it's been a while since I have worked
> on PPC and don't feel comfortable adding "Reviewed-by" for PPC code. :-/
Sure, I understand. As long as the rest of the changes look fine, that's=20
good. Michael Ellerman wrote the -mprofile-kernel ftrace_caller()=20
implementation, so I'll look forward to his review of that part.
- Naveen
=
^ permalink raw reply
* [RFC v2 4/4] powerpc/hotplug/drcinfo: Improve code for ibm,drc-info device processing
From: Michael Bringmann @ 2018-03-21 18:27 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Bringmann, Nathan Fontenot, John Allen, Tyrel Datwyler,
Thomas Falcon
In-Reply-To: <9ed45428-fdad-a945-55df-3d47959204fb@linux.vnet.ibm.com>
This patch extends the use of a common parse function for the
ibm,drc-info property that can be modified by a callback function
to the hotplug device processing. Candidate code is replaced by
a call to the parser including a pointer to a local context-specific
functions, and local data.
In addition, the original set missed several opportunities to compress
and reuse common code which this patch attempts to provide.
Finally, a bug with the registration of slots was observed on some
systems, and the code was rewritten to prevent its reoccurrence.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
Fixes: 3f38000eda48 ("powerpc/firmware: Add definitions for new drc-info firmwar
e feature" -- end of patch series applied to powerpc next)
---
Changes in V2:
-- Update code to account for v4.16 kernel checkins.
-- Fix bug searching for virtual device slots.
---
drivers/pci/hotplug/rpaphp_core.c | 188 ++++++++++++++++++++++++++-----------
1 file changed, 130 insertions(+), 58 deletions(-)
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index dccdf62..974147a 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -222,49 +222,52 @@ static int rpaphp_check_drc_props_v1(struct device_node *dn, char *drc_name,
return -EINVAL;
}
-static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
- char *drc_type, unsigned int my_index)
+struct check_drc_props_v2_struct {
+ char *drc_name;
+ char *drc_type;
+ unsigned int my_index;
+};
+
+static int check_drc_props_v2_checkRun(struct of_drc_info *drc,
+ void *idata, void *not_used,
+ int *ret_code)
{
- struct property *info;
- unsigned int entries;
- struct of_drc_info drc;
- const __be32 *value;
+ struct check_drc_props_v2_struct *cdata = idata;
char cell_drc_name[MAX_DRC_NAME_LEN];
- int j, fndit;
-
- info = of_find_property(dn->parent, "ibm,drc-info", NULL);
- if (info == NULL)
- return -EINVAL;
-
- value = of_prop_next_u32(info, NULL, &entries);
- if (!value)
- return -EINVAL;
- value++;
-
- for (j = 0; j < entries; j++) {
- of_read_drc_info_cell(&info, &value, &drc);
- /* Should now know end of current entry */
+ (*ret_code) = -EINVAL;
- if (my_index > drc.last_drc_index)
- continue;
+ if (cdata->my_index > drc->last_drc_index)
+ return 0;
- fndit = 1;
- break;
+ /* Found drc_index. Now match the rest. */
+ sprintf(cell_drc_name, "%s%d", drc->drc_name_prefix,
+ cdata->my_index - drc->drc_index_start +
+ drc->drc_name_suffix_start);
+
+ if (((cdata->drc_name == NULL) ||
+ (cdata->drc_name && !strcmp(cdata->drc_name, cell_drc_name))) &&
+ ((cdata->drc_type == NULL) ||
+ (cdata->drc_type && !strcmp(cdata->drc_type, drc->drc_type)))) {
+ (*ret_code) = 0;
+ return 1;
}
- /* Found it */
- if (fndit)
- sprintf(cell_drc_name, "%s%d", drc.drc_name_prefix,
- my_index);
+ return 0;
+}
- if (((drc_name == NULL) ||
- (drc_name && !strcmp(drc_name, cell_drc_name))) &&
- ((drc_type == NULL) ||
- (drc_type && !strcmp(drc_type, drc.drc_type))))
- return 0;
+static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
+ char *drc_type, unsigned int my_index)
+{
+ struct device_node *root = dn;
+ struct check_drc_props_v2_struct cdata = {
+ drc_name, drc_type, be32_to_cpu(my_index) };
- return -EINVAL;
+ if (!drc_type || (drc_type && strcmp(drc_type, "SLOT")))
+ root = dn->parent;
+
+ return drc_info_parser(root, check_drc_props_v2_checkRun,
+ drc_type, &cdata);
}
int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
@@ -287,7 +290,6 @@ int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
}
EXPORT_SYMBOL_GPL(rpaphp_check_drc_props);
-
static int is_php_type(char *drc_type)
{
unsigned long value;
@@ -347,17 +349,40 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
*
* To remove a slot, it suffices to call rpaphp_deregister_slot().
*/
-int rpaphp_add_slot(struct device_node *dn)
+
+static int rpaphp_add_slot_common(struct device_node *dn,
+ u32 drc_index, char *drc_name, char *drc_type,
+ u32 drc_power_domain)
{
struct slot *slot;
int retval = 0;
- int i;
+
+ slot = alloc_slot_struct(dn, drc_index, drc_name,
+ drc_power_domain);
+ if (!slot)
+ return -ENOMEM;
+
+ slot->type = simple_strtoul(drc_type, NULL, 10);
+
+ dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
+ drc_index, drc_name, drc_type);
+
+ retval = rpaphp_enable_slot(slot);
+ if (!retval)
+ retval = rpaphp_register_slot(slot);
+
+ if (retval)
+ dealloc_slot_struct(slot);
+
+ return retval;
+}
+
+static int rpaphp_add_slot_v1(struct device_node *dn)
+{
+ int i, retval = 0;
const int *indexes, *names, *types, *power_domains;
char *name, *type;
- if (!dn->name || strcmp(dn->name, "pci"))
- return 0;
-
/* If this is not a hotplug slot, return without doing anything. */
if (!is_php_dn(dn, &indexes, &names, &types, &power_domains))
return 0;
@@ -368,25 +393,13 @@ int rpaphp_add_slot(struct device_node *dn)
name = (char *) &names[1];
type = (char *) &types[1];
for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
- int index;
-
- index = be32_to_cpu(indexes[i + 1]);
- slot = alloc_slot_struct(dn, index, name,
- be32_to_cpu(power_domains[i + 1]));
- if (!slot)
- return -ENOMEM;
-
- slot->type = simple_strtoul(type, NULL, 10);
-
- dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n",
- index, name, type);
-
- retval = rpaphp_enable_slot(slot);
+
+ retval = rpaphp_add_slot_common(dn,
+ be32_to_cpu(indexes[i + 1]),
+ name, type,
+ be32_to_cpu(power_domains[i + 1]));
if (!retval)
- retval = rpaphp_register_slot(slot);
-
- if (retval)
- dealloc_slot_struct(slot);
+ return retval;
name += strlen(name) + 1;
type += strlen(type) + 1;
@@ -396,6 +409,65 @@ int rpaphp_add_slot(struct device_node *dn)
/* XXX FIXME: reports a failure only if last entry in loop failed */
return retval;
}
+
+struct rpaphp_add_slot_v2_struct {
+ struct device_node *dn;
+};
+
+static int rpaphp_add_slot_v2_checkRun(struct of_drc_info *drc,
+ void *idata, void *not_used,
+ int *ret_code)
+{
+ struct rpaphp_add_slot_v2_struct *cdata = idata;
+ u32 drc_index;
+ char drc_name[MAX_DRC_NAME_LEN];
+ int i, retval;
+
+ (*ret_code) = -EINVAL;
+
+ if (!is_php_type((char *) drc->drc_type)) {
+ (*ret_code) = 0;
+ return 1;
+ }
+
+ for (i = 0, drc_index = drc->drc_index_start;
+ i < drc->num_sequential_elems; i++, drc_index++) {
+
+ sprintf(drc_name, "%s%d", drc->drc_name_prefix,
+ drc_index - drc->drc_index_start +
+ drc->drc_name_suffix_start);
+
+ retval = rpaphp_add_slot_common(cdata->dn,
+ drc_index, drc_name, drc->drc_type,
+ drc->drc_power_domain);
+ if (!retval) {
+ (*ret_code) = retval;
+ return 1;
+ }
+ }
+
+ (*ret_code) = retval;
+ return 0;
+}
+
+static int rpaphp_add_slot_v2(struct device_node *dn)
+{
+ struct rpaphp_add_slot_v2_struct cdata = { dn };
+
+ return drc_info_parser(dn, rpaphp_add_slot_v2_checkRun,
+ NULL, &cdata);
+}
+
+int rpaphp_add_slot(struct device_node *dn)
+{
+ if (!dn->name || strcmp(dn->name, "pci"))
+ return 0;
+
+ if (firmware_has_feature(FW_FEATURE_DRC_INFO))
+ return rpaphp_add_slot_v2(dn);
+ else
+ return rpaphp_add_slot_v1(dn);
+}
EXPORT_SYMBOL_GPL(rpaphp_add_slot);
static void __exit cleanup_slots(void)
^ permalink raw reply related
* [RFC v2 3/4] powerpc/hotplug/drcinfo: Fix hot-add CPU issues
From: Michael Bringmann @ 2018-03-21 18:26 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Bringmann, Nathan Fontenot, John Allen, Tyrel Datwyler,
Thomas Falcon
In-Reply-To: <9ed45428-fdad-a945-55df-3d47959204fb@linux.vnet.ibm.com>
This patch applies a common parse function for the ibm,drc-info
property that can be modified by a callback function to the
hot-add CPU code. Candidate code is replaced by a call to the
parser including a pointer to a local context-specific functions,
and local data.
In addition, a bug in the release of the previous patch set may
break things in some of the CPU DLPAR operations. For instance,
when attempting to hot-add a new CPU or set of CPUs, the original
patch failed to always properly calculate the available resources,
and aborted the operation.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
Fixes: 3f38000eda48 ("powerpc/firmware: Add definitions for new drc-info firmwar
e feature" -- end of patch series applied to powerpc next)
---
Changes in V2:
-- Update code to account for v4.16 kernel checkins.
---
arch/powerpc/platforms/pseries/hotplug-cpu.c | 129 +++++++++++++++++------
arch/powerpc/platforms/pseries/pseries_energy.c | 112 ++++++++++----------
2 files changed, 154 insertions(+), 87 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 652d3e96..0811fb0 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -411,25 +411,67 @@ static bool dlpar_cpu_exists(struct device_node *parent, u32 drc_index)
return found;
}
-static bool valid_cpu_drc_index(struct device_node *parent, u32 drc_index)
+static bool check_cpu_drc_index(struct device_node *parent,
+ int (*checkRun)(struct of_drc_info *drc,
+ void *data,
+ void *not_used,
+ int *ret_code),
+ void *cdata)
{
- bool found = false;
- int rc, index;
+ int found = 0;
+
+ if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
+ found = drc_info_parser(parent, checkRun, "CPU", cdata);
+ } else {
+ int rc, index = 0;
- index = 0;
- while (!found) {
- u32 drc;
+ while (!found) {
+ u32 drc;
- rc = of_property_read_u32_index(parent, "ibm,drc-indexes",
+ rc = of_property_read_u32_index(parent,
+ "ibm,drc-indexes",
index++, &drc);
- if (rc)
- break;
+ if (rc)
+ break;
+ found = checkRun(NULL, cdata, &drc, NULL);
+ }
+ }
- if (drc == drc_index)
- found = true;
+ return (bool)found;
+}
+
+struct valid_cpu_drc_index_struct {
+ u32 targ_drc_index;
+};
+
+static int valid_cpu_drc_index_checkRun(struct of_drc_info *drc,
+ void *idata,
+ void *drc_index,
+ int *ret_code)
+{
+ struct valid_cpu_drc_index_struct *cdata = idata;
+
+ if (drc) {
+ if ((drc->drc_index_start <= cdata->targ_drc_index) &&
+ (cdata->targ_drc_index <= drc->last_drc_index)) {
+ (*ret_code) = 1;
+ return 1;
+ }
+ } else {
+ if (*((u32*)drc_index) == cdata->targ_drc_index) {
+ (*ret_code) = 1;
+ return 1;
+ }
}
+ return 0;
+}
- return found;
+static bool valid_cpu_drc_index(struct device_node *parent, u32 drc_index)
+{
+ struct valid_cpu_drc_index_struct cdata = { drc_index };
+
+ return check_cpu_drc_index(parent, valid_cpu_drc_index_checkRun,
+ &cdata);
}
static ssize_t dlpar_cpu_add(u32 drc_index)
@@ -721,11 +763,45 @@ static int dlpar_cpu_remove_by_count(u32 cpus_to_remove)
return rc;
}
+struct find_dlpar_cpus_to_add_struct {
+ struct device_node *parent;
+ u32 *cpu_drcs;
+ u32 cpus_to_add;
+ u32 cpus_found;
+};
+
+static int find_dlpar_cpus_to_add_checkRun(struct of_drc_info *drc,
+ void *idata,
+ void *drc_index,
+ int *ret_code)
+{
+ struct find_dlpar_cpus_to_add_struct *cdata = idata;
+
+ if (drc) {
+ int k;
+
+ for (k = 0; (k < drc->num_sequential_elems) &&
+ (cdata->cpus_found < cdata->cpus_to_add); k++) {
+ u32 idrc = drc->drc_index_start +
+ (k * drc->sequential_inc);
+
+ if (dlpar_cpu_exists(cdata->parent, idrc))
+ continue;
+ cdata->cpu_drcs[cdata->cpus_found++] = idrc;
+ }
+ } else {
+ if (!dlpar_cpu_exists(cdata->parent, *((u32*)drc_index)))
+ cdata->cpu_drcs[cdata->cpus_found++] =
+ *((u32*)drc_index);
+ }
+ return 0;
+}
+
static int find_dlpar_cpus_to_add(u32 *cpu_drcs, u32 cpus_to_add)
{
struct device_node *parent;
- int cpus_found = 0;
- int index, rc;
+ struct find_dlpar_cpus_to_add_struct cdata = {
+ NULL, cpu_drcs, cpus_to_add, 0 };
parent = of_find_node_by_path("/cpus");
if (!parent) {
@@ -734,28 +810,15 @@ static int find_dlpar_cpus_to_add(u32 *cpu_drcs, u32 cpus_to_add)
return -1;
}
- /* Search the ibm,drc-indexes array for possible CPU drcs to
- * add. Note that the format of the ibm,drc-indexes array is
- * the number of entries in the array followed by the array
- * of drc values so we start looking at index = 1.
+ /* Search the appropriate property for possible CPU drcs to
+ * add.
*/
- index = 1;
- while (cpus_found < cpus_to_add) {
- u32 drc;
-
- rc = of_property_read_u32_index(parent, "ibm,drc-indexes",
- index++, &drc);
- if (rc)
- break;
-
- if (dlpar_cpu_exists(parent, drc))
- continue;
-
- cpu_drcs[cpus_found++] = drc;
- }
+ cdata.parent = parent;
+ check_cpu_drc_index(parent, find_dlpar_cpus_to_add_checkRun,
+ &cdata);
of_node_put(parent);
- return cpus_found;
+ return cdata.cpus_found;
}
static int dlpar_cpu_add_by_count(u32 cpus_to_add)
diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c
index c7d84aa..332f3ce 100644
--- a/arch/powerpc/platforms/pseries/pseries_energy.c
+++ b/arch/powerpc/platforms/pseries/pseries_energy.c
@@ -36,6 +36,26 @@
/* Helper Routines to convert between drc_index to cpu numbers */
+struct cpu_to_drc_index_struct {
+ u32 thread_index;
+ u32 ret;
+};
+
+static int cpu_to_drc_index_checkRun(struct of_drc_info *drc,
+ void *idata, void *not_used, int *ret_code)
+{
+ struct cpu_to_drc_index_struct *cdata = idata;
+
+ if (cdata->thread_index < drc->last_drc_index) {
+ cdata->ret = drc->drc_index_start +
+ (cdata->thread_index * drc->sequential_inc);
+ (*ret_code) = 1;
+ return 1;
+ }
+ (*ret_code) = 0;
+ return 0;
+}
+
static u32 cpu_to_drc_index(int cpu)
{
struct device_node *dn = NULL;
@@ -51,32 +71,16 @@ static u32 cpu_to_drc_index(int cpu)
thread_index = cpu_core_index_of_thread(cpu);
if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
- struct property *info = NULL;
- struct of_drc_info drc;
- int j;
- u32 num_set_entries;
- const __be32 *value;
-
- info = of_find_property(dn, "ibm,drc-info", NULL);
- if (info == NULL)
- goto err_of_node_put;
+ struct cpu_to_drc_index_struct cdata = {
+ thread_index, 0 };
- value = of_prop_next_u32(info, NULL, &num_set_entries);
- if (!value)
- goto err_of_node_put;
- value++;
-
- for (j = 0; j < num_set_entries; j++) {
+ rc = drc_info_parser(dn, &cpu_to_drc_index_checkRun,
+ "CPU", &cdata);
- of_read_drc_info_cell(&info, &value, &drc);
- if (strncmp(drc.drc_type, "CPU", 3))
- goto err;
-
- if (thread_index < drc.last_drc_index)
- break;
- }
+ if (rc < 0)
+ goto err_of_node_put;
- ret = drc.drc_index_start + (thread_index * drc.sequential_inc);
+ ret = cdata.ret;
} else {
const __be32 *indexes;
@@ -102,11 +106,36 @@ static u32 cpu_to_drc_index(int cpu)
return ret;
}
+struct drc_index_to_cpu_struct {
+ u32 drc_index;
+ u32 thread_index;
+ u32 cpu;
+};
+
+static int drc_index_to_cpu_checkRun(struct of_drc_info *drc,
+ void *idata, void *not_used, int *ret_code)
+{
+ struct drc_index_to_cpu_struct *cdata = idata;
+
+ if (cdata->drc_index > drc->last_drc_index) {
+ cdata->cpu += drc->num_sequential_elems;
+ (*ret_code) = 0;
+ return 0;
+ } else {
+ cdata->cpu += ((cdata->drc_index - drc->drc_index_start) /
+ drc->sequential_inc);
+
+ cdata->thread_index = cpu_first_thread_of_core(cdata->cpu);
+ (*ret_code) = 0;
+ return 0;
+ }
+}
+
static int drc_index_to_cpu(u32 drc_index)
{
struct device_node *dn = NULL;
const int *indexes;
- int thread_index = 0, cpu = 0;
+ int thread_index = 0;
int rc = 1;
dn = of_find_node_by_path("/cpus");
@@ -114,38 +143,13 @@ static int drc_index_to_cpu(u32 drc_index)
goto err;
if (firmware_has_feature(FW_FEATURE_DRC_INFO)) {
- struct property *info = NULL;
- struct of_drc_info drc;
- int j;
- u32 num_set_entries;
- const __be32 *value;
-
- info = of_find_property(dn, "ibm,drc-info", NULL);
- if (info == NULL)
- goto err_of_node_put;
-
- value = of_prop_next_u32(info, NULL, &num_set_entries);
- if (!value)
- goto err_of_node_put;
- value++;
-
- for (j = 0; j < num_set_entries; j++) {
+ struct drc_index_to_cpu_struct cdata = {
+ drc_index, 0, 0 };
- of_read_drc_info_cell(&info, &value, &drc);
- if (strncmp(drc.drc_type, "CPU", 3))
- goto err;
+ rc = drc_info_parser(dn, &drc_index_to_cpu_checkRun,
+ "CPU", &cdata);
+ thread_index = cdata.thread_index;
- if (drc_index > drc.last_drc_index) {
- cpu += drc.num_sequential_elems;
- continue;
- }
- cpu += ((drc_index - drc.drc_index_start) /
- drc.sequential_inc);
-
- thread_index = cpu_first_thread_of_core(cpu);
- rc = 0;
- break;
- }
} else {
unsigned long int i;
^ permalink raw reply related
* [RFC v2 2/4] powerpc/hotplug/drcinfo: Provide common parser for ibm,drc-info
From: Michael Bringmann @ 2018-03-21 18:26 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Bringmann, Nathan Fontenot, John Allen, Tyrel Datwyler,
Thomas Falcon
In-Reply-To: <9ed45428-fdad-a945-55df-3d47959204fb@linux.vnet.ibm.com>
This patch provides a common parse function for the ibm,drc-info
property that can be modified by a callback function. The caller
provides a pointer to the function and a pointer to their unique
data, and the parser provides the current lmb set from the struct.
The callback function may return codes indicating that the parsing
is complete, or should continue, along with an error code that may
be returned to the caller.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
Fixes: 3f38000eda48 ("powerpc/firmware: Add definitions for new drc-info firmwar
e feature" -- end of patch series applied to powerpc next)
---
Changes in V2:
-- Update code to account for v4.16 kernel checkins.
---
arch/powerpc/include/asm/prom.h | 7 +++
arch/powerpc/platforms/pseries/Makefile | 2 -
arch/powerpc/platforms/pseries/drchelpers.c | 66 +++++++++++++++++++++++++++
3 files changed, 74 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/platforms/pseries/drchelpers.c
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index b04c5ce..2e947b3 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -94,6 +94,13 @@ struct of_drc_info {
extern int of_read_drc_info_cell(struct property **prop,
const __be32 **curval, struct of_drc_info *data);
+extern int drc_info_parser(struct device_node *dn,
+ int (*usercb)(struct of_drc_info *drc,
+ void *data,
+ void *optional_data,
+ int *ret_code),
+ char *opt_drc_type,
+ void *data);
/*
* There are two methods for telling firmware what our capabilities are.
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 13eede6..38c8547 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -3,7 +3,7 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG
obj-y := lpar.o hvCall.o nvram.o reconfig.o \
- of_helpers.o \
+ of_helpers.o drchelpers.o \
setup.o iommu.o event_sources.o ras.o \
firmware.o power.o dlpar.o mobility.o rng.o \
pci.o pci_dlpar.o eeh_pseries.o msi.o
diff --git a/arch/powerpc/platforms/pseries/drchelpers.c b/arch/powerpc/platforms/pseries/drchelpers.c
new file mode 100644
index 0000000..556e05d
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/drchelpers.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 Michael Bringmann <mbringm@us.ibm.com>, IBM
+ *
+ * pSeries specific routines for device-tree properties.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+
+#include <asm/prom.h>
+#include "pseries.h"
+
+#define MAX_DRC_NAME_LEN 64
+
+int drc_info_parser(struct device_node *dn,
+ int (*usercb)(struct of_drc_info *drc,
+ void *data,
+ void *optional_data,
+ int *ret_code),
+ char *opt_drc_type,
+ void *data)
+{
+ struct property *info;
+ unsigned int entries;
+ struct of_drc_info drc;
+ const __be32 *value;
+ int j, done = 0, ret_code = -EINVAL;
+
+ info = of_find_property(dn, "ibm,drc-info", NULL);
+ if (info == NULL)
+ return -EINVAL;
+
+ value = of_prop_next_u32(info, NULL, &entries);
+ if (!value)
+ return -EINVAL;
+ value++;
+
+ for (j = 0, done = 0; (j < entries) && (!done); j++) {
+ of_read_drc_info_cell(&info, &value, &drc);
+
+ if (opt_drc_type && strcmp(opt_drc_type, drc.drc_type))
+ continue;
+
+ done = usercb(&drc, data, NULL, &ret_code);
+ }
+
+ return ret_code;
+}
+EXPORT_SYMBOL(drc_info_parser);
^ permalink raw reply related
* [RFC v2 1/4] powerpc/hotplug/drcinfo: Fix bugs parsing ibm,drc-info structs
From: Michael Bringmann @ 2018-03-21 18:26 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Bringmann, Nathan Fontenot, John Allen, Tyrel Datwyler,
Thomas Falcon
In-Reply-To: <9ed45428-fdad-a945-55df-3d47959204fb@linux.vnet.ibm.com>
[Replace/withdraw previous patch submission to ensure that testing
of related patches on similar hardware progresses together.]
This patch fixes a memory parsing bug when using of_prop_next_u32
calls at the start of a structure. Depending upon the value of
"cur" memory pointer argument to of_prop_next_u32, it will or it
won't advance the value of the returned memory pointer by the
size of one u32. This patch corrects the code to deal with that
indexing feature when parsing the ibm,drc-info structs for CPUs.
Also, need to advance the pointer at the end of_read_drc_info_cell
for same reason.
Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
Fixes: 3f38000eda48 ("powerpc/firmware: Add definitions for new drc-info firmware feature" -- end of patch series applied to powerpc next)
---
arch/powerpc/platforms/pseries/of_helpers.c | 5 ++---
arch/powerpc/platforms/pseries/pseries_energy.c | 2 ++
drivers/pci/hotplug/rpaphp_core.c | 1 +
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c
index 6df192f..20598b2 100644
--- a/arch/powerpc/platforms/pseries/of_helpers.c
+++ b/arch/powerpc/platforms/pseries/of_helpers.c
@@ -65,9 +65,7 @@ int of_read_drc_info_cell(struct property **prop, const __be32 **curval,
/* Get drc-index-start:encode-int */
p2 = (const __be32 *)p;
- p2 = of_prop_next_u32(*prop, p2, &data->drc_index_start);
- if (!p2)
- return -EINVAL;
+ data->drc_index_start = of_read_number(p2, 1);
/* Get drc-name-suffix-start:encode-int */
p2 = of_prop_next_u32(*prop, p2, &data->drc_name_suffix_start);
@@ -88,6 +86,7 @@ int of_read_drc_info_cell(struct property **prop, const __be32 **curval,
p2 = of_prop_next_u32(*prop, p2, &data->drc_power_domain);
if (!p2)
return -EINVAL;
+ p2++;
/* Should now know end of current entry */
(*curval) = (void *)p2;
diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c
index 6ed2212..c7d84aa 100644
--- a/arch/powerpc/platforms/pseries/pseries_energy.c
+++ b/arch/powerpc/platforms/pseries/pseries_energy.c
@@ -64,6 +64,7 @@ static u32 cpu_to_drc_index(int cpu)
value = of_prop_next_u32(info, NULL, &num_set_entries);
if (!value)
goto err_of_node_put;
+ value++;
for (j = 0; j < num_set_entries; j++) {
@@ -126,6 +127,7 @@ static int drc_index_to_cpu(u32 drc_index)
value = of_prop_next_u32(info, NULL, &num_set_entries);
if (!value)
goto err_of_node_put;
+ value++;
for (j = 0; j < num_set_entries; j++) {
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index fb5e084..dccdf62 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -239,6 +239,7 @@ static int rpaphp_check_drc_props_v2(struct device_node *dn, char *drc_name,
value = of_prop_next_u32(info, NULL, &entries);
if (!value)
return -EINVAL;
+ value++;
for (j = 0; j < entries; j++) {
of_read_drc_info_cell(&info, &value, &drc);
^ permalink raw reply related
* [RFC v2 0/4] powerpc/drcinfo: Fix bugs 'ibm,drc-info' property
From: Michael Bringmann @ 2018-03-21 18:26 UTC (permalink / raw)
To: linuxppc-dev
Cc: Michael Bringmann, Nathan Fontenot, John Allen, Tyrel Datwyler,
Thomas Falcon
This patch set corrects some errors and omissions in the previous
set of patches adding support for the "ibm,drc-info" property to
powerpc systems.
Unfortunately, some errors in the previous patch set break things
in some of the DLPAR operations. In particular when attempting to
hot-add a new CPU or set of CPUs, the original patch failed to
properly calculate the available resources, and aborted the operation.
In addition, the original set missed several opportunities to compress
and reuse common code, especially, in the area of device processing.
Signed-off-by: Michael W. Bringmann <mwb@linux.vnet.ibm.com>
---
Changes in V2:
-- Update code for v4.16 kernel checkins.
-- Fix bug with virtual devices.
^ permalink raw reply
* Re: [PATCH v2 5/5] powerpc64/ftrace: Implement support for ftrace_regs_caller()
From: Steven Rostedt @ 2018-03-21 15:31 UTC (permalink / raw)
To: Naveen N. Rao
Cc: Anton Blanchard, linuxppc-dev, Michael Ellerman, Nicholas Piggin,
Paul Mackerras, sathnaga
In-Reply-To: <1521646126.5jxja0sxh5.naveen@linux.ibm.com>
On Wed, 21 Mar 2018 20:59:03 +0530
"Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
> Thanks for the review!
You're welcome. Note, I did put "Acked-by" and not "Reviewed-by"
because my "Reviewed-by" is usually a bit more thorough than what I did
for your patches. That's because it's been a while since I have worked
on PPC and don't feel comfortable adding "Reviewed-by" for PPC code. :-/
-- Steve
^ permalink raw reply
* Re: [PATCH v2 5/5] powerpc64/ftrace: Implement support for ftrace_regs_caller()
From: Naveen N. Rao @ 2018-03-21 15:29 UTC (permalink / raw)
To: Steven Rostedt
Cc: Anton Blanchard, linuxppc-dev, Michael Ellerman, Nicholas Piggin,
Paul Mackerras, sathnaga
In-Reply-To: <20180321112221.16cd9c3c@gandalf.local.home>
Steven Rostedt wrote:
> On Wed, 21 Mar 2018 20:07:32 +0530
> "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
>=20
>> I think that will always be set here. ftrace_64_mprofile.S is only built=
=20
>> for -mprofile-kernel and we select HAVE_DYNAMIC_FTRACE_WITH_REGS if=20
>> MPROFILE_KERNEL is enabled. It looks like there is no way to unset just=20
>> CONFIG_DYNAMIC_FTRACE_WITH_REGS and so, for -mprofile-kernel, we can=20
>> assume it is always set?
>=20
> OK, if that's the case, then I'm fine with it.
Thanks for the review!
- Naveen
=
^ permalink raw reply
* Re: [PATCH v2 5/5] powerpc64/ftrace: Implement support for ftrace_regs_caller()
From: Steven Rostedt @ 2018-03-21 15:22 UTC (permalink / raw)
To: Naveen N. Rao
Cc: Anton Blanchard, linuxppc-dev, Michael Ellerman, Nicholas Piggin,
Paul Mackerras, sathnaga
In-Reply-To: <1521642624.97rikdhoqw.naveen@linux.ibm.com>
On Wed, 21 Mar 2018 20:07:32 +0530
"Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
> I think that will always be set here. ftrace_64_mprofile.S is only built
> for -mprofile-kernel and we select HAVE_DYNAMIC_FTRACE_WITH_REGS if
> MPROFILE_KERNEL is enabled. It looks like there is no way to unset just
> CONFIG_DYNAMIC_FTRACE_WITH_REGS and so, for -mprofile-kernel, we can
> assume it is always set?
OK, if that's the case, then I'm fine with it.
-- Steve
^ permalink raw reply
* Re: RFC on writel and writel_relaxed
From: Sinan Kaya @ 2018-03-21 15:04 UTC (permalink / raw)
To: David Laight, Oliver
Cc: linux-rdma@vger.kernel.org,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT)
In-Reply-To: <8a13375fd8e5439890768b7dd8473099@AcuMS.aculab.com>
On 3/21/2018 9:35 AM, David Laight wrote:
>> x86 has compiler barrier inside the relaxed() API so that code does not
>> get reordered. ARM64 architecturally guarantees device writes to be observed
>> in order.
>
> There are places where you don't even need a compile barrier between
> every write.
>
> I had horrid problems getting some ppc code (for a specific embedded SoC)
> optimised to have no extra barriers.
> I ended up just writing through 'pointer to volatile' and adding an
> explicit 'eieio' between the block of writes and status read.
>
> No less painful was doing a byteswapping write to normal memory.
If the architecture is reordering writes to the peripheral, then removing
the compiler barrier can break the multi-arch drivers. barriers document
clearly states that device need to observe writes in order.
Though for special cases like you mentioned, you can certainly do this:
wmb()
__raw_write/pointer access
__raw_write/pointer access
__raw_write/pointer access
/* flush everything */
mmiowb()
__raw_write/pointer access
There would be no ordering guarantee between the wmb() and mmiowb().
This can only be done for known code and known hardware. I don't believe
this applies to multi-arch drivers.
>
> David
>
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* RE: RFC on writel and writel_relaxed
From: David Laight @ 2018-03-21 14:35 UTC (permalink / raw)
To: 'Sinan Kaya', Oliver
Cc: linux-rdma@vger.kernel.org,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT)
In-Reply-To: <4e5c745a-8b9b-959e-8893-d99cd6032484@codeaurora.org>
PiB4ODYgaGFzIGNvbXBpbGVyIGJhcnJpZXIgaW5zaWRlIHRoZSByZWxheGVkKCkgQVBJIHNvIHRo
YXQgY29kZSBkb2VzIG5vdA0KPiBnZXQgcmVvcmRlcmVkLiBBUk02NCBhcmNoaXRlY3R1cmFsbHkg
Z3VhcmFudGVlcyBkZXZpY2Ugd3JpdGVzIHRvIGJlIG9ic2VydmVkDQo+IGluIG9yZGVyLg0KDQpU
aGVyZSBhcmUgcGxhY2VzIHdoZXJlIHlvdSBkb24ndCBldmVuIG5lZWQgYSBjb21waWxlIGJhcnJp
ZXIgYmV0d2Vlbg0KZXZlcnkgd3JpdGUuDQoNCkkgaGFkIGhvcnJpZCBwcm9ibGVtcyBnZXR0aW5n
IHNvbWUgcHBjIGNvZGUgKGZvciBhIHNwZWNpZmljIGVtYmVkZGVkIFNvQykNCm9wdGltaXNlZCB0
byBoYXZlIG5vIGV4dHJhIGJhcnJpZXJzLg0KSSBlbmRlZCB1cCBqdXN0IHdyaXRpbmcgdGhyb3Vn
aCAncG9pbnRlciB0byB2b2xhdGlsZScgYW5kIGFkZGluZyBhbg0KZXhwbGljaXQgJ2VpZWlvJyBi
ZXR3ZWVuIHRoZSBibG9jayBvZiB3cml0ZXMgYW5kIHN0YXR1cyByZWFkLg0KDQpObyBsZXNzIHBh
aW5mdWwgd2FzIGRvaW5nIGEgYnl0ZXN3YXBwaW5nIHdyaXRlIHRvIG5vcm1hbCBtZW1vcnkuDQoN
CglEYXZpZA0KDQo=
^ permalink raw reply
* Re: [PATCH v2 5/5] powerpc64/ftrace: Implement support for ftrace_regs_caller()
From: Naveen N. Rao @ 2018-03-21 14:37 UTC (permalink / raw)
To: Steven Rostedt
Cc: Anton Blanchard, linuxppc-dev, Michael Ellerman, Nicholas Piggin,
Paul Mackerras, sathnaga
In-Reply-To: <20180321095912.212e0b0d@gandalf.local.home>
Steven Rostedt wrote:
> On Wed, 21 Mar 2018 16:13:22 +0530
> "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
>=20
>> int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
>> {
>> mod->arch.toc =3D my_r2(sechdrs, mod);
>> - mod->arch.tramp =3D create_ftrace_stub(sechdrs, mod);
>> + mod->arch.tramp =3D create_ftrace_stub(sechdrs, mod,
>> + (unsigned long)ftrace_caller);
>> +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
>> + mod->arch.tramp_regs =3D create_ftrace_stub(sechdrs, mod,
>> + (unsigned long)ftrace_regs_caller);
>=20
> So you only reference ftrace_regs_caller if you have
> DYNAMIC_FTRACE_WITH_REGS defined?
Yes.
>=20
>> + if (!mod->arch.tramp_regs)
>> + return -ENOENT;
>> +#endif
>> =20
>> if (!mod->arch.tramp)
>> return -ENOENT;
>=20
>=20
>> diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/power=
pc/kernel/trace/ftrace_64_mprofile.S
>> index 8f2380304ef1..7b81db85f76e 100644
>> --- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
>> +++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
>> @@ -20,8 +20,8 @@
>> #ifdef CONFIG_DYNAMIC_FTRACE
>> /*
>> *
>> - * ftrace_caller() is the function that replaces _mcount() when ftrace =
is
>> - * active.
>> + * ftrace_caller()/ftrace_regs_caller() is the function that replaces _=
mcount()
>> + * when ftrace is active.
>> *
>> * We arrive here after a function A calls function B, and we are the t=
race
>> * function for B. When we enter r1 points to A's stack frame, B has no=
t yet
>> @@ -37,7 +37,7 @@
>> * Our job is to save the register state into a struct pt_regs (on the =
stack)
>> * and then arrange for the ftrace function to be called.
>> */
>=20
> Perhaps you want to add:
>=20
> #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
>=20
> here.
I think that will always be set here. ftrace_64_mprofile.S is only built=20
for -mprofile-kernel and we select HAVE_DYNAMIC_FTRACE_WITH_REGS if=20
MPROFILE_KERNEL is enabled. It looks like there is no way to unset just=20
CONFIG_DYNAMIC_FTRACE_WITH_REGS and so, for -mprofile-kernel, we can=20
assume it is always set?
- Naveen
=
^ permalink raw reply
* [PATCH v2 2/2] powerpc/mm: Trace tlbia instruction
From: Christophe Leroy @ 2018-03-21 14:17 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev, Balbir Singh
In-Reply-To: <7c34db8eca67beefa7ec8243bc07135b4dff4440.1521641523.git.christophe.leroy@c-s.fr>
Add a trace point for tlbia (Translation Lookaside Buffer Invalidate
All) instruction.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/trace.h | 15 +++++++++++++++
arch/powerpc/mm/mmu_decl.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h
index 33f3b479138b..0165a424308d 100644
--- a/arch/powerpc/include/asm/trace.h
+++ b/arch/powerpc/include/asm/trace.h
@@ -202,6 +202,21 @@ TRACE_EVENT(tlbie,
__entry->r)
);
+TRACE_EVENT(tlbia,
+
+ TP_PROTO(unsigned long id),
+ TP_ARGS(id),
+ TP_STRUCT__entry(
+ __field(unsigned long, id)
+ ),
+
+ TP_fast_assign(
+ __entry->id = id;
+ ),
+
+ TP_printk("ctx.id=0x%lx", __entry->id)
+);
+
#endif /* _TRACE_POWERPC_H */
#undef TRACE_INCLUDE_PATH
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 107033cc4dcf..8f5483e415dd 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -32,10 +32,12 @@
static inline void _tlbil_all(void)
{
asm volatile ("sync; tlbia; isync" : : : "memory");
+ trace_tlbia(MMU_NO_CONTEXT);
}
static inline void _tlbil_pid(unsigned int pid)
{
asm volatile ("sync; tlbia; isync" : : : "memory");
+ trace_tlbia(pid);
}
#define _tlbil_pid_noind(pid) _tlbil_pid(pid)
--
2.13.3
^ permalink raw reply related
* [PATCH v2 1/2] powerpc/mm: Add missing tracepoint for tlbie
From: Christophe Leroy @ 2018-03-21 14:16 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev, Balbir Singh
commit 0428491cba927 ("powerpc/mm: Trace tlbie(l) instructions")
added tracepoints for tlbie calls, but _tlbil_va() was forgotten
Fixes: 0428491cba927 ("powerpc/mm: Trace tlbie(l) instructions")
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/mmu_decl.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 57fbc554c785..107033cc4dcf 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -23,6 +23,7 @@
#include <asm/mmu.h>
#ifdef CONFIG_PPC_MMU_NOHASH
+#include <asm/trace.h>
/*
* On 40x and 8xx, we directly inline tlbia and tlbivax
@@ -56,6 +57,7 @@ static inline void _tlbil_va(unsigned long address, unsigned int pid,
unsigned int tsize, unsigned int ind)
{
asm volatile ("tlbie %0; sync" : : "r" (address) : "memory");
+ trace_tlbie(0, 0, address, pid, 0, 0, 0);
}
#elif defined(CONFIG_PPC_BOOK3E)
extern void _tlbil_va(unsigned long address, unsigned int pid,
--
2.13.3
^ permalink raw reply related
* [PATCH 4/4] powerpc/mm: Remove stale_map[] handling on non SMP processors
From: Christophe Leroy @ 2018-03-21 14:07 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev
In-Reply-To: <03c175e506e88e57f48f01de9120768e1b942c6e.1521641042.git.christophe.leroy@c-s.fr>
stale_map[] bits are only set in steal_context_smp() so
on UP processors this map is useless. Only manage it for SMP
processors.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/mmu_context_nohash.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
index 625c17049483..3f13f07f64dd 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -88,7 +88,9 @@
static unsigned int next_context, nr_free_contexts;
static unsigned long *context_map;
+#ifdef CONFIG_SMP
static unsigned long *stale_map[NR_CPUS];
+#endif
static struct mm_struct **context_mm;
static DEFINE_RAW_SPINLOCK(context_lock);
@@ -169,7 +171,9 @@ static unsigned int steal_context_smp(unsigned int id)
static unsigned int steal_all_contexts(void)
{
struct mm_struct *mm;
+#ifdef CONFIG_SMP
int cpu = smp_processor_id();
+#endif
unsigned int id;
for (id = FIRST_CONTEXT; id <= LAST_CONTEXT; id++) {
@@ -187,7 +191,9 @@ static unsigned int steal_all_contexts(void)
mm->context.active = 0;
#endif
}
+#ifdef CONFIG_SMP
__clear_bit(id, stale_map[cpu]);
+#endif
}
/* Flush the TLB for all contexts (not to be used on SMP) */
@@ -206,7 +212,9 @@ static unsigned int steal_all_contexts(void)
static unsigned int steal_context_up(unsigned int id)
{
struct mm_struct *mm;
+#ifdef CONFIG_SMP
int cpu = smp_processor_id();
+#endif
/* Pick up the victim mm */
mm = context_mm[id];
@@ -220,7 +228,9 @@ static unsigned int steal_context_up(unsigned int id)
mm->context.id = MMU_NO_CONTEXT;
/* XXX This clear should ultimately be part of local_flush_tlb_mm */
+#ifdef CONFIG_SMP
__clear_bit(id, stale_map[cpu]);
+#endif
return id;
}
@@ -259,7 +269,10 @@ static void context_check_map(void) { }
void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
- unsigned int i, id, cpu = smp_processor_id();
+ unsigned int id;
+#ifdef CONFIG_SMP
+ unsigned int i, cpu = smp_processor_id();
+#endif
unsigned long *map;
/* No lockless fast path .. yet */
@@ -333,6 +346,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
/* If that context got marked stale on this CPU, then flush the
* local TLB for it and unmark it before we use it
*/
+#ifdef CONFIG_SMP
if (test_bit(id, stale_map[cpu])) {
pr_hardcont(" | stale flush %d [%d..%d]",
id, cpu_first_thread_sibling(cpu),
@@ -347,6 +361,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
__clear_bit(id, stale_map[i]);
}
}
+#endif
/* Flick the MMU and release lock */
pr_hardcont(" -> %d\n", id);
@@ -452,9 +467,7 @@ void __init mmu_context_init(void)
*/
context_map = memblock_virt_alloc(CTX_MAP_SIZE, 0);
context_mm = memblock_virt_alloc(sizeof(void *) * (LAST_CONTEXT + 1), 0);
-#ifndef CONFIG_SMP
- stale_map[0] = memblock_virt_alloc(CTX_MAP_SIZE, 0);
-#else
+#ifdef CONFIG_SMP
stale_map[boot_cpuid] = memblock_virt_alloc(CTX_MAP_SIZE, 0);
cpuhp_setup_state_nocalls(CPUHP_POWERPC_MMU_CTX_PREPARE,
--
2.13.3
^ permalink raw reply related
* [PATCH 3/4] powerpc/mm: constify LAST_CONTEXT in mmu_context_nohash
From: Christophe Leroy @ 2018-03-21 14:07 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev
In-Reply-To: <03c175e506e88e57f48f01de9120768e1b942c6e.1521641042.git.christophe.leroy@c-s.fr>
last_context is 16 on the 8xx, 65535 on the 47x and 255 on other ones.
The kernel is exclusively built for the 8xx, for the 47x or for
another processor so the last context can be defined as a constant
depending on the processor.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/mmu_context_nohash.c | 88 ++++++++++++++++++------------------
1 file changed, 43 insertions(+), 45 deletions(-)
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
index 3fbe36266838..625c17049483 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -54,9 +54,38 @@
#include "mmu_decl.h"
+/*
+ * The MPC8xx has only 16 contexts. We rotate through them on each
+ * task switch. A better way would be to keep track of tasks that
+ * own contexts, and implement an LRU usage. That way very active
+ * tasks don't always have to pay the TLB reload overhead. The
+ * kernel pages are mapped shared, so the kernel can run on behalf
+ * of any task that makes a kernel entry. Shared does not mean they
+ * are not protected, just that the ASID comparison is not performed.
+ * -- Dan
+ *
+ * The IBM4xx has 256 contexts, so we can just rotate through these
+ * as a way of "switching" contexts. If the TID of the TLB is zero,
+ * the PID/TID comparison is disabled, so we can use a TID of zero
+ * to represent all kernel pages as shared among all contexts.
+ * -- Dan
+ *
+ * The IBM 47x core supports 16-bit PIDs, thus 65535 contexts. We
+ * should normally never have to steal though the facility is
+ * present if needed.
+ * -- BenH
+ */
#define FIRST_CONTEXT 1
+#ifdef DEBUG_CLAMP_LAST_CONTEXT
+#define LAST_CONTEXT DEBUG_CLAMP_LAST_CONTEXT
+#elif defined(CONFIG_PPC_8xx)
+#define LAST_CONTEXT 16
+#elif defined(CONFIG_PPC_47x)
+#define LAST_CONTEXT 65535
+#else
+#define LAST_CONTEXT 255
+#endif
-static unsigned int last_context;
static unsigned int next_context, nr_free_contexts;
static unsigned long *context_map;
static unsigned long *stale_map[NR_CPUS];
@@ -64,7 +93,7 @@ static struct mm_struct **context_mm;
static DEFINE_RAW_SPINLOCK(context_lock);
#define CTX_MAP_SIZE \
- (sizeof(unsigned long) * (last_context / BITS_PER_LONG + 1))
+ (sizeof(unsigned long) * (LAST_CONTEXT / BITS_PER_LONG + 1))
/* Steal a context from a task that has one at the moment.
@@ -88,7 +117,7 @@ static unsigned int steal_context_smp(unsigned int id)
struct mm_struct *mm;
unsigned int cpu, max, i;
- max = last_context - FIRST_CONTEXT;
+ max = LAST_CONTEXT - FIRST_CONTEXT;
/* Attempt to free next_context first and then loop until we manage */
while (max--) {
@@ -100,7 +129,7 @@ static unsigned int steal_context_smp(unsigned int id)
*/
if (mm->context.active) {
id++;
- if (id > last_context)
+ if (id > LAST_CONTEXT)
id = FIRST_CONTEXT;
continue;
}
@@ -143,7 +172,7 @@ static unsigned int steal_all_contexts(void)
int cpu = smp_processor_id();
unsigned int id;
- for (id = FIRST_CONTEXT; id <= last_context; id++) {
+ for (id = FIRST_CONTEXT; id <= LAST_CONTEXT; id++) {
/* Pick up the victim mm */
mm = context_mm[id];
@@ -164,7 +193,7 @@ static unsigned int steal_all_contexts(void)
/* Flush the TLB for all contexts (not to be used on SMP) */
_tlbil_all();
- nr_free_contexts = last_context - FIRST_CONTEXT;
+ nr_free_contexts = LAST_CONTEXT - FIRST_CONTEXT;
return FIRST_CONTEXT;
}
@@ -202,7 +231,7 @@ static void context_check_map(void)
unsigned int id, nrf, nact;
nrf = nact = 0;
- for (id = FIRST_CONTEXT; id <= last_context; id++) {
+ for (id = FIRST_CONTEXT; id <= LAST_CONTEXT; id++) {
int used = test_bit(id, context_map);
if (!used)
nrf++;
@@ -264,7 +293,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
/* We really don't have a context, let's try to acquire one */
id = next_context;
- if (id > last_context)
+ if (id > LAST_CONTEXT)
id = FIRST_CONTEXT;
map = context_map;
@@ -288,8 +317,8 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
/* We know there's at least one free context, try to find it */
while (__test_and_set_bit(id, map)) {
- id = find_next_zero_bit(map, last_context+1, id);
- if (id > last_context)
+ id = find_next_zero_bit(map, LAST_CONTEXT+1, id);
+ if (id > LAST_CONTEXT)
id = FIRST_CONTEXT;
}
stolen:
@@ -419,41 +448,10 @@ void __init mmu_context_init(void)
init_mm.context.active = NR_CPUS;
/*
- * The MPC8xx has only 16 contexts. We rotate through them on each
- * task switch. A better way would be to keep track of tasks that
- * own contexts, and implement an LRU usage. That way very active
- * tasks don't always have to pay the TLB reload overhead. The
- * kernel pages are mapped shared, so the kernel can run on behalf
- * of any task that makes a kernel entry. Shared does not mean they
- * are not protected, just that the ASID comparison is not performed.
- * -- Dan
- *
- * The IBM4xx has 256 contexts, so we can just rotate through these
- * as a way of "switching" contexts. If the TID of the TLB is zero,
- * the PID/TID comparison is disabled, so we can use a TID of zero
- * to represent all kernel pages as shared among all contexts.
- * -- Dan
- *
- * The IBM 47x core supports 16-bit PIDs, thus 65535 contexts. We
- * should normally never have to steal though the facility is
- * present if needed.
- * -- BenH
- */
- if (mmu_has_feature(MMU_FTR_TYPE_8xx))
- last_context = 16;
- else if (mmu_has_feature(MMU_FTR_TYPE_47x))
- last_context = 65535;
- else
- last_context = 255;
-
-#ifdef DEBUG_CLAMP_LAST_CONTEXT
- last_context = DEBUG_CLAMP_LAST_CONTEXT;
-#endif
- /*
* Allocate the maps used by context management
*/
context_map = memblock_virt_alloc(CTX_MAP_SIZE, 0);
- context_mm = memblock_virt_alloc(sizeof(void *) * (last_context + 1), 0);
+ context_mm = memblock_virt_alloc(sizeof(void *) * (LAST_CONTEXT + 1), 0);
#ifndef CONFIG_SMP
stale_map[0] = memblock_virt_alloc(CTX_MAP_SIZE, 0);
#else
@@ -466,8 +464,8 @@ void __init mmu_context_init(void)
printk(KERN_INFO
"MMU: Allocated %zu bytes of context maps for %d contexts\n",
- 2 * CTX_MAP_SIZE + (sizeof(void *) * (last_context + 1)),
- last_context - FIRST_CONTEXT + 1);
+ 2 * CTX_MAP_SIZE + (sizeof(void *) * (LAST_CONTEXT + 1)),
+ LAST_CONTEXT - FIRST_CONTEXT + 1);
/*
* Some processors have too few contexts to reserve one for
@@ -477,6 +475,6 @@ void __init mmu_context_init(void)
*/
context_map[0] = (1 << FIRST_CONTEXT) - 1;
next_context = FIRST_CONTEXT;
- nr_free_contexts = last_context - FIRST_CONTEXT + 1;
+ nr_free_contexts = LAST_CONTEXT - FIRST_CONTEXT + 1;
}
--
2.13.3
^ permalink raw reply related
* [PATCH 2/4] powerpc/mm: Avoid unnecessary test and reduce code size
From: Christophe Leroy @ 2018-03-21 14:07 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev
In-Reply-To: <03c175e506e88e57f48f01de9120768e1b942c6e.1521641042.git.christophe.leroy@c-s.fr>
no_selective_tlbil hence the use of either steal_all_contexts()
or steal_context_up() depends on the subarch, it won't change
during run. Only the 8xx uses steal_all_contexts and CONFIG_PPC_8xx
is exclusive of other processors.
This patch replaces the test of no_selective_tlbil global var by
a test of CONFIG_PPC_8xx selection. It avoids the test and
removes unnecessary code.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/mmu_context_nohash.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
index 5051c9363f8c..3fbe36266838 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -62,7 +62,6 @@ static unsigned long *context_map;
static unsigned long *stale_map[NR_CPUS];
static struct mm_struct **context_mm;
static DEFINE_RAW_SPINLOCK(context_lock);
-static bool no_selective_tlbil;
#define CTX_MAP_SIZE \
(sizeof(unsigned long) * (last_context / BITS_PER_LONG + 1))
@@ -279,7 +278,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
goto stolen;
}
#endif /* CONFIG_SMP */
- if (no_selective_tlbil)
+ if (IS_ENABLED(CONFIG_PPC_8xx))
id = steal_all_contexts();
else
id = steal_context_up(id);
@@ -440,16 +439,12 @@ void __init mmu_context_init(void)
* present if needed.
* -- BenH
*/
- if (mmu_has_feature(MMU_FTR_TYPE_8xx)) {
+ if (mmu_has_feature(MMU_FTR_TYPE_8xx))
last_context = 16;
- no_selective_tlbil = true;
- } else if (mmu_has_feature(MMU_FTR_TYPE_47x)) {
+ else if (mmu_has_feature(MMU_FTR_TYPE_47x))
last_context = 65535;
- no_selective_tlbil = false;
- } else {
+ else
last_context = 255;
- no_selective_tlbil = false;
- }
#ifdef DEBUG_CLAMP_LAST_CONTEXT
last_context = DEBUG_CLAMP_LAST_CONTEXT;
--
2.13.3
^ permalink raw reply related
* [PATCH 1/4] powerpc/mm: constify FIRST_CONTEXT in mmu_context_nohash
From: Christophe Leroy @ 2018-03-21 14:07 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev
First context is now 1 for all supported platforms, so it
can be made a constant.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/mmu_context_nohash.c | 37 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
index be8f5c9d4d08..5051c9363f8c 100644
--- a/arch/powerpc/mm/mmu_context_nohash.c
+++ b/arch/powerpc/mm/mmu_context_nohash.c
@@ -54,7 +54,9 @@
#include "mmu_decl.h"
-static unsigned int first_context, last_context;
+#define FIRST_CONTEXT 1
+
+static unsigned int last_context;
static unsigned int next_context, nr_free_contexts;
static unsigned long *context_map;
static unsigned long *stale_map[NR_CPUS];
@@ -87,7 +89,7 @@ static unsigned int steal_context_smp(unsigned int id)
struct mm_struct *mm;
unsigned int cpu, max, i;
- max = last_context - first_context;
+ max = last_context - FIRST_CONTEXT;
/* Attempt to free next_context first and then loop until we manage */
while (max--) {
@@ -100,7 +102,7 @@ static unsigned int steal_context_smp(unsigned int id)
if (mm->context.active) {
id++;
if (id > last_context)
- id = first_context;
+ id = FIRST_CONTEXT;
continue;
}
pr_hardcont(" | steal %d from 0x%p", id, mm);
@@ -142,7 +144,7 @@ static unsigned int steal_all_contexts(void)
int cpu = smp_processor_id();
unsigned int id;
- for (id = first_context; id <= last_context; id++) {
+ for (id = FIRST_CONTEXT; id <= last_context; id++) {
/* Pick up the victim mm */
mm = context_mm[id];
@@ -150,7 +152,7 @@ static unsigned int steal_all_contexts(void)
/* Mark this mm as having no context anymore */
mm->context.id = MMU_NO_CONTEXT;
- if (id != first_context) {
+ if (id != FIRST_CONTEXT) {
context_mm[id] = NULL;
__clear_bit(id, context_map);
#ifdef DEBUG_MAP_CONSISTENCY
@@ -163,9 +165,9 @@ static unsigned int steal_all_contexts(void)
/* Flush the TLB for all contexts (not to be used on SMP) */
_tlbil_all();
- nr_free_contexts = last_context - first_context;
+ nr_free_contexts = last_context - FIRST_CONTEXT;
- return first_context;
+ return FIRST_CONTEXT;
}
/* Note that this will also be called on SMP if all other CPUs are
@@ -201,7 +203,7 @@ static void context_check_map(void)
unsigned int id, nrf, nact;
nrf = nact = 0;
- for (id = first_context; id <= last_context; id++) {
+ for (id = FIRST_CONTEXT; id <= last_context; id++) {
int used = test_bit(id, context_map);
if (!used)
nrf++;
@@ -219,7 +221,7 @@ static void context_check_map(void)
if (nact > num_online_cpus())
pr_err("MMU: More active contexts than CPUs ! (%d vs %d)\n",
nact, num_online_cpus());
- if (first_context > 0 && !test_bit(0, context_map))
+ if (FIRST_CONTEXT > 0 && !test_bit(0, context_map))
pr_err("MMU: Context 0 has been freed !!!\n");
}
#else
@@ -264,7 +266,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
/* We really don't have a context, let's try to acquire one */
id = next_context;
if (id > last_context)
- id = first_context;
+ id = FIRST_CONTEXT;
map = context_map;
/* No more free contexts, let's try to steal one */
@@ -289,7 +291,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
while (__test_and_set_bit(id, map)) {
id = find_next_zero_bit(map, last_context+1, id);
if (id > last_context)
- id = first_context;
+ id = FIRST_CONTEXT;
}
stolen:
next_context = id + 1;
@@ -439,15 +441,12 @@ void __init mmu_context_init(void)
* -- BenH
*/
if (mmu_has_feature(MMU_FTR_TYPE_8xx)) {
- first_context = 1;
last_context = 16;
no_selective_tlbil = true;
} else if (mmu_has_feature(MMU_FTR_TYPE_47x)) {
- first_context = 1;
last_context = 65535;
no_selective_tlbil = false;
} else {
- first_context = 1;
last_context = 255;
no_selective_tlbil = false;
}
@@ -473,16 +472,16 @@ void __init mmu_context_init(void)
printk(KERN_INFO
"MMU: Allocated %zu bytes of context maps for %d contexts\n",
2 * CTX_MAP_SIZE + (sizeof(void *) * (last_context + 1)),
- last_context - first_context + 1);
+ last_context - FIRST_CONTEXT + 1);
/*
* Some processors have too few contexts to reserve one for
* init_mm, and require using context 0 for a normal task.
* Other processors reserve the use of context zero for the kernel.
- * This code assumes first_context < 32.
+ * This code assumes FIRST_CONTEXT < 32.
*/
- context_map[0] = (1 << first_context) - 1;
- next_context = first_context;
- nr_free_contexts = last_context - first_context + 1;
+ context_map[0] = (1 << FIRST_CONTEXT) - 1;
+ next_context = FIRST_CONTEXT;
+ nr_free_contexts = last_context - FIRST_CONTEXT + 1;
}
--
2.13.3
^ permalink raw reply related
* Re: [PATCH v2 5/5] powerpc64/ftrace: Implement support for ftrace_regs_caller()
From: Steven Rostedt @ 2018-03-21 13:59 UTC (permalink / raw)
To: Naveen N. Rao
Cc: Michael Ellerman, Paul Mackerras, linuxppc-dev, Anton Blanchard,
Nicholas Piggin, sathnaga
In-Reply-To: <764a63e7418b05185434fe660814ce762c93c7d0.1521627906.git.naveen.n.rao@linux.vnet.ibm.com>
On Wed, 21 Mar 2018 16:13:22 +0530
"Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
> int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
> {
> mod->arch.toc = my_r2(sechdrs, mod);
> - mod->arch.tramp = create_ftrace_stub(sechdrs, mod);
> + mod->arch.tramp = create_ftrace_stub(sechdrs, mod,
> + (unsigned long)ftrace_caller);
> +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
> + mod->arch.tramp_regs = create_ftrace_stub(sechdrs, mod,
> + (unsigned long)ftrace_regs_caller);
So you only reference ftrace_regs_caller if you have
DYNAMIC_FTRACE_WITH_REGS defined?
> + if (!mod->arch.tramp_regs)
> + return -ENOENT;
> +#endif
>
> if (!mod->arch.tramp)
> return -ENOENT;
> diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
> index 8f2380304ef1..7b81db85f76e 100644
> --- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
> +++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
> @@ -20,8 +20,8 @@
> #ifdef CONFIG_DYNAMIC_FTRACE
> /*
> *
> - * ftrace_caller() is the function that replaces _mcount() when ftrace is
> - * active.
> + * ftrace_caller()/ftrace_regs_caller() is the function that replaces _mcount()
> + * when ftrace is active.
> *
> * We arrive here after a function A calls function B, and we are the trace
> * function for B. When we enter r1 points to A's stack frame, B has not yet
> @@ -37,7 +37,7 @@
> * Our job is to save the register state into a struct pt_regs (on the stack)
> * and then arrange for the ftrace function to be called.
> */
Perhaps you want to add:
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
here.
> -_GLOBAL(ftrace_caller)
> +_GLOBAL(ftrace_regs_caller)
> /* Save the original return address in A's stack frame */
> std r0,LRSAVE(r1)
>
> @@ -100,8 +100,8 @@ _GLOBAL(ftrace_caller)
> addi r6, r1 ,STACK_FRAME_OVERHEAD
>
> /* ftrace_call(r3, r4, r5, r6) */
> -.globl ftrace_call
> -ftrace_call:
> +.globl ftrace_regs_call
> +ftrace_regs_call:
> bl ftrace_stub
> nop
>
> @@ -162,6 +162,7 @@ ftrace_call:
> bne- livepatch_handler
> #endif
>
> +ftrace_caller_common:
> #ifdef CONFIG_FUNCTION_GRAPH_TRACER
> .globl ftrace_graph_call
> ftrace_graph_call:
> @@ -182,6 +183,66 @@ ftrace_no_trace:
> mtlr r0
> bctr
>
> +_GLOBAL(ftrace_caller)
> + /* Save the original return address in A's stack frame */
> + std r0, LRSAVE(r1)
> +
> + /* Create our stack frame + pt_regs */
> + stdu r1, -SWITCH_FRAME_SIZE(r1)
> +
> + /* Save all gprs to pt_regs */
> + SAVE_8GPRS(3, r1)
> +
> + lbz r3, PACA_FTRACE_DISABLED(r13)
> + cmpdi r3, 0
> + beq ftrace_no_trace
Of course you would need to keep the ftrace_no_trace part out of the
#if block then.
-- Steve
> +
> + /* Get the _mcount() call site out of LR */
> + mflr r7
> + std r7, _NIP(r1)
> +
> + /* Save callee's TOC in the ABI compliant location */
> + std r2, 24(r1)
> + ld r2, PACATOC(r13) /* get kernel TOC in r2 */
> +
> + addis r3, r2, function_trace_op@toc@ha
> + addi r3, r3, function_trace_op@toc@l
> + ld r5, 0(r3)
> +
> + /* Calculate ip from nip-4 into r3 for call below */
> + subi r3, r7, MCOUNT_INSN_SIZE
> +
> + /* Put the original return address in r4 as parent_ip */
> + mr r4, r0
> +
> + /* Set pt_regs to NULL */
> + li r6, 0
> +
> + /* ftrace_call(r3, r4, r5, r6) */
> +.globl ftrace_call
> +ftrace_call:
> + bl ftrace_stub
> + nop
> +
> + ld r3, _NIP(r1)
> + mtctr r3
> +
> + /* Restore gprs */
> + REST_8GPRS(3,r1)
> +
> + /* Restore callee's TOC */
> + ld r2, 24(r1)
> +
> + /* Pop our stack frame */
> + addi r1, r1, SWITCH_FRAME_SIZE
> +
> + /* Reload original LR */
> + ld r0, LRSAVE(r1)
> + mtlr r0
> +
> + /* Handle function_graph or go back */
> + b ftrace_caller_common
> +
> #ifdef CONFIG_LIVEPATCH
> /*
> * This function runs in the mcount context, between two functions. As
^ permalink raw reply
* Re: RFC on writel and writel_relaxed
From: Sinan Kaya @ 2018-03-21 13:58 UTC (permalink / raw)
To: Oliver
Cc: open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
linux-rdma@vger.kernel.org, Benjamin Herrenschmidt
In-Reply-To: <4e5c745a-8b9b-959e-8893-d99cd6032484@codeaurora.org>
On 3/21/2018 8:53 AM, Sinan Kaya wrote:
> BTW, I have no idea what compiler barrier does on PPC and if
>
> wrltel() == compiler barrier() + wrltel_relaxed()
>
> can be said.
this should have been
writel_relaxed() == compiler barrier() + __raw_writel()
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* Re: RFC on writel and writel_relaxed
From: Sinan Kaya @ 2018-03-21 13:53 UTC (permalink / raw)
To: Oliver
Cc: open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
linux-rdma@vger.kernel.org, Benjamin Herrenschmidt
In-Reply-To: <CAOSf1CFmoK2XSn0=qAtiVEO9t4i-DHGgfieiedDfuO6E3tpkQw@mail.gmail.com>
On 3/20/2018 10:40 PM, Oliver wrote:
>> I see that network drivers are working around the issue by calling
>> __raw_write() API directly but this also breaks other architectures
>> like SPARC since the semantics of __raw_writel() seems to be system dependent.
> Yeah that's pretty gross. Which drivers are doing this?
>
Searching for __raw_writel() and BIG_ENDIAN in drivers/net directory
should give you the idea.
In a nutshell, drivers are doing this today.
wmb()
__raw_writel();
mmiowb()
I'm in the process of posting patches ([1], [2], [3]) to various subsystems to
eliminate double barriers by replacing sequences like
wmb()
writel()
mmiowb()
with
wmb()
writel_relaxed()
mmiowb()
Reviewers pointed out that writel_relaxed() is not __raw_writel() on PPC
and cannot take advantage of the optimization.
Replacing writel_relaxed() with raw_writel() or vice versa is not correct.
writel_relaxed() needs to have ordering guarantees with respect to the order
device observes writes.
x86 has compiler barrier inside the relaxed() API so that code does not
get reordered. ARM64 architecturally guarantees device writes to be observed
in order.
I was hoping that PPC could follow x86 and inject compiler barrier into the
relaxed functions.
BTW, I have no idea what compiler barrier does on PPC and if
wrltel() == compiler barrier() + wrltel_relaxed()
can be said.
Need guidance from the PPC maintainers.
[1] https://www.spinics.net/lists/netdev/msg490480.html
[2] https://www.spinics.net/lists/arm-kernel/msg642341.html
[3] https://www.spinics.net/lists/arm-kernel/msg642336.html
--
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH 1/2] powerpc/time: inline arch_vtime_task_switch()
From: Christophe Leroy @ 2018-03-21 13:52 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev
arch_vtime_task_switch() is a small function which is called
only from vtime_common_task_switch(), so it is worth inlining
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/cputime.h | 15 ++++++++++++++-
arch/powerpc/kernel/time.c | 21 ---------------------
2 files changed, 14 insertions(+), 22 deletions(-)
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h
index 99b541865d8d..36345341dd70 100644
--- a/arch/powerpc/include/asm/cputime.h
+++ b/arch/powerpc/include/asm/cputime.h
@@ -47,9 +47,22 @@ static inline unsigned long cputime_to_usecs(const cputime_t ct)
* has to be populated in the new task
*/
#ifdef CONFIG_PPC64
+#define get_accounting(tsk) (&get_paca()->accounting)
static inline void arch_vtime_task_switch(struct task_struct *tsk) { }
#else
-void arch_vtime_task_switch(struct task_struct *tsk);
+#define get_accounting(tsk) (&task_thread_info(tsk)->accounting)
+/*
+ * Called from the context switch with interrupts disabled, to charge all
+ * accumulated times to the current process, and to prepare accounting on
+ * the next process.
+ */
+static inline void arch_vtime_task_switch(struct task_struct *prev)
+{
+ struct cpu_accounting_data *acct = get_accounting(current);
+
+ acct->starttime = get_accounting(prev)->starttime;
+ acct->startspurr = get_accounting(prev)->startspurr;
+}
#endif
#endif /* __KERNEL__ */
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index a32823dcd9a4..aa6aa5d4a60c 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -163,12 +163,6 @@ EXPORT_SYMBOL(__cputime_usec_factor);
void (*dtl_consumer)(struct dtl_entry *, u64);
#endif
-#ifdef CONFIG_PPC64
-#define get_accounting(tsk) (&get_paca()->accounting)
-#else
-#define get_accounting(tsk) (&task_thread_info(tsk)->accounting)
-#endif
-
static void calc_cputime_factors(void)
{
struct div_result res;
@@ -418,21 +412,6 @@ void vtime_flush(struct task_struct *tsk)
acct->softirq_time = 0;
}
-#ifdef CONFIG_PPC32
-/*
- * Called from the context switch with interrupts disabled, to charge all
- * accumulated times to the current process, and to prepare accounting on
- * the next process.
- */
-void arch_vtime_task_switch(struct task_struct *prev)
-{
- struct cpu_accounting_data *acct = get_accounting(current);
-
- acct->starttime = get_accounting(prev)->starttime;
- acct->startspurr = get_accounting(prev)->startspurr;
-}
-#endif /* CONFIG_PPC32 */
-
#else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
#define calc_cputime_factors()
#endif
--
2.13.3
^ permalink raw reply related
* [PATCH 2/2] powerpc/time: Only set ARCH_HAS_SCALED_CPUTIME on PPC64
From: Christophe Leroy @ 2018-03-21 13:52 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood
Cc: linux-kernel, linuxppc-dev
In-Reply-To: <fbbdc0bcff276190ea8619b3070d971f2ca76abd.1521639065.git.christophe.leroy@c-s.fr>
scaled cputime is only meaningfull when the processor has
SPURR and/or PURR, which means only on PPC64.
Removing it on PPC32 significantly reduces the size of
vtime_account_system() and vtime_account_idle() on an 8xx:
Before:
00000114 l F .text 000000a8 vtime_delta
000004c0 g F .text 00000100 vtime_account_system
000005c0 g F .text 00000048 vtime_account_idle
After:
(vtime_delta gets inlined in the two functions)
00000418 g F .text 000000a0 vtime_account_system
000004b8 g F .text 00000054 vtime_account_idle
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/accounting.h | 4 ++++
arch/powerpc/include/asm/cputime.h | 2 ++
arch/powerpc/kernel/time.c | 29 +++++++++++++++++++++++------
4 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 0c76d93d5da5..8c9f54779ff1 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -142,7 +142,7 @@ config PPC
select ARCH_HAS_PHYS_TO_DMA
select ARCH_HAS_PMEM_API if PPC64
select ARCH_HAS_MEMBARRIER_CALLBACKS
- select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE
+ select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC64
select ARCH_HAS_SG_CHAIN
select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION)
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
diff --git a/arch/powerpc/include/asm/accounting.h b/arch/powerpc/include/asm/accounting.h
index 3abcf98ed2e0..f1096d4cc658 100644
--- a/arch/powerpc/include/asm/accounting.h
+++ b/arch/powerpc/include/asm/accounting.h
@@ -15,8 +15,10 @@ struct cpu_accounting_data {
/* Accumulated cputime values to flush on ticks*/
unsigned long utime;
unsigned long stime;
+#ifdef ARCH_HAS_SCALED_CPUTIME
unsigned long utime_scaled;
unsigned long stime_scaled;
+#endif
unsigned long gtime;
unsigned long hardirq_time;
unsigned long softirq_time;
@@ -25,8 +27,10 @@ struct cpu_accounting_data {
/* Internal counters */
unsigned long starttime; /* TB value snapshot */
unsigned long starttime_user; /* TB value on exit to usermode */
+#ifdef ARCH_HAS_SCALED_CPUTIME
unsigned long startspurr; /* SPURR value snapshot */
unsigned long utime_sspurr; /* ->user_time when ->startspurr set */
+#endif
};
#endif
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h
index 36345341dd70..c11d4fd27028 100644
--- a/arch/powerpc/include/asm/cputime.h
+++ b/arch/powerpc/include/asm/cputime.h
@@ -61,7 +61,9 @@ static inline void arch_vtime_task_switch(struct task_struct *prev)
struct cpu_accounting_data *acct = get_accounting(current);
acct->starttime = get_accounting(prev)->starttime;
+#ifdef ARCH_HAS_SCALED_CPUTIME
acct->startspurr = get_accounting(prev)->startspurr;
+#endif
}
#endif
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index aa6aa5d4a60c..09e5eb9f0e81 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -175,6 +175,7 @@ static void calc_cputime_factors(void)
* Read the SPURR on systems that have it, otherwise the PURR,
* or if that doesn't exist return the timebase value passed in.
*/
+#ifdef ARCH_HAS_SCALED_CPUTIME
static unsigned long read_spurr(unsigned long tb)
{
if (cpu_has_feature(CPU_FTR_SPURR))
@@ -183,6 +184,7 @@ static unsigned long read_spurr(unsigned long tb)
return mfspr(SPRN_PURR);
return tb;
}
+#endif
#ifdef CONFIG_PPC_SPLPAR
@@ -282,22 +284,28 @@ static unsigned long vtime_delta(struct task_struct *tsk,
unsigned long *stime_scaled,
unsigned long *steal_time)
{
- unsigned long now, nowscaled, deltascaled;
+ unsigned long now;
unsigned long stime;
+#ifdef ARCH_HAS_SCALED_CPUTIME
+ unsigned long nowscaled, deltascaled;
unsigned long utime, utime_scaled;
+#endif
struct cpu_accounting_data *acct = get_accounting(tsk);
WARN_ON_ONCE(!irqs_disabled());
now = mftb();
+#ifdef ARCH_HAS_SCALED_CPUTIME
nowscaled = read_spurr(now);
+#endif
stime = now - acct->starttime;
acct->starttime = now;
- deltascaled = nowscaled - acct->startspurr;
- acct->startspurr = nowscaled;
*steal_time = calculate_stolen_time(now);
+#ifdef ARCH_HAS_SCALED_CPUTIME
+ deltascaled = nowscaled - acct->startspurr;
+ acct->startspurr = nowscaled;
utime = acct->utime - acct->utime_sspurr;
acct->utime_sspurr = acct->utime;
@@ -322,6 +330,7 @@ static unsigned long vtime_delta(struct task_struct *tsk,
}
}
acct->utime_scaled += utime_scaled;
+#endif
return stime;
}
@@ -338,7 +347,9 @@ void vtime_account_system(struct task_struct *tsk)
if ((tsk->flags & PF_VCPU) && !irq_count()) {
acct->gtime += stime;
+#ifdef ARCH_HAS_SCALED_CPUTIME
acct->utime_scaled += stime_scaled;
+#endif
} else {
if (hardirq_count())
acct->hardirq_time += stime;
@@ -347,7 +358,9 @@ void vtime_account_system(struct task_struct *tsk)
else
acct->stime += stime;
+#ifdef ARCH_HAS_SCALED_CPUTIME
acct->stime_scaled += stime_scaled;
+#endif
}
}
EXPORT_SYMBOL_GPL(vtime_account_system);
@@ -375,8 +388,12 @@ void vtime_flush(struct task_struct *tsk)
if (acct->utime)
account_user_time(tsk, cputime_to_nsecs(acct->utime));
+#ifdef ARCH_HAS_SCALED_CPUTIME
if (acct->utime_scaled)
tsk->utimescaled += cputime_to_nsecs(acct->utime_scaled);
+ if (acct->stime_scaled)
+ tsk->stimescaled += cputime_to_nsecs(acct->stime_scaled);
+#endif
if (acct->gtime)
account_guest_time(tsk, cputime_to_nsecs(acct->gtime));
@@ -390,8 +407,6 @@ void vtime_flush(struct task_struct *tsk)
if (acct->stime)
account_system_index_time(tsk, cputime_to_nsecs(acct->stime),
CPUTIME_SYSTEM);
- if (acct->stime_scaled)
- tsk->stimescaled += cputime_to_nsecs(acct->stime_scaled);
if (acct->hardirq_time)
account_system_index_time(tsk, cputime_to_nsecs(acct->hardirq_time),
@@ -401,13 +416,15 @@ void vtime_flush(struct task_struct *tsk)
CPUTIME_SOFTIRQ);
acct->utime = 0;
+#ifdef ARCH_HAS_SCALED_CPUTIME
acct->utime_scaled = 0;
acct->utime_sspurr = 0;
+ acct->stime_scaled = 0;
+#endif
acct->gtime = 0;
acct->steal_time = 0;
acct->idle_time = 0;
acct->stime = 0;
- acct->stime_scaled = 0;
acct->hardirq_time = 0;
acct->softirq_time = 0;
}
--
2.13.3
^ 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