* Re: [PATCH kernel v2 0/7] powerpc/powenv/ioda: Allow huge DMA window at 4GB
From: Alexey Kardashevskiy @ 2020-04-08 9:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Alistair Popple, Fabiano Rosas, kvm, kvm-ppc, David Gibson
In-Reply-To: <20200323075354.93825-1-aik@ozlabs.ru>
On 23/03/2020 18:53, Alexey Kardashevskiy wrote:
> Here is an attempt to support bigger DMA space for devices
> supporting DMA masks less than 59 bits (GPUs come into mind
> first). POWER9 PHBs have an option to map 2 windows at 0
> and select a windows based on DMA address being below or above
> 4GB.
>
> This adds the "iommu=iommu_bypass" kernel parameter and
> supports VFIO+pseries machine - current this requires telling
> upstream+unmodified QEMU about this via
> -global spapr-pci-host-bridge.dma64_win_addr=0x100000000
> or per-phb property. 4/4 advertises the new option but
> there is no automation around it in QEMU (should it be?).
>
> For now it is either 1<<59 or 4GB mode; dynamic switching is
> not supported (could be via sysfs).
>
> This is a rebased version of
> https://lore.kernel.org/kvm/20191202015953.127902-1-aik@ozlabs.ru/
>
> The main change since v1 is that now it is 7 patches with
> clearer separation of steps.
>
>
> This is based on 6c90b86a745a "Merge tag 'mmc-v5.6-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc"
>
> Please comment. Thanks.
Ping?
>
>
>
> Alexey Kardashevskiy (7):
> powerpc/powernv/ioda: Move TCE bypass base to PE
> powerpc/powernv/ioda: Rework for huge DMA window at 4GB
> powerpc/powernv/ioda: Allow smaller TCE table levels
> powerpc/powernv/phb4: Use IOMMU instead of bypassing
> powerpc/iommu: Add a window number to
> iommu_table_group_ops::get_table_size
> powerpc/powernv/phb4: Add 4GB IOMMU bypass mode
> vfio/spapr_tce: Advertise and allow a huge DMA windows at 4GB
>
> arch/powerpc/include/asm/iommu.h | 3 +
> arch/powerpc/include/asm/opal-api.h | 9 +-
> arch/powerpc/include/asm/opal.h | 2 +
> arch/powerpc/platforms/powernv/pci.h | 4 +-
> include/uapi/linux/vfio.h | 2 +
> arch/powerpc/platforms/powernv/npu-dma.c | 1 +
> arch/powerpc/platforms/powernv/opal-call.c | 2 +
> arch/powerpc/platforms/powernv/pci-ioda-tce.c | 4 +-
> arch/powerpc/platforms/powernv/pci-ioda.c | 234 ++++++++++++++----
> drivers/vfio/vfio_iommu_spapr_tce.c | 17 +-
> 10 files changed, 213 insertions(+), 65 deletions(-)
>
--
Alexey
^ permalink raw reply
* Re: [RFC] Support stop state version quirk and firmware enabled stop
From: Gautham R Shenoy @ 2020-04-08 9:50 UTC (permalink / raw)
To: Pratik Rajesh Sampat
Cc: ego, mikey, pratik.r.sampat, vaidy, linux-kernel, npiggin,
linuxppc-dev, oohall, skiboot
In-Reply-To: <20200304155648.11501-1-psampat@linux.ibm.com>
Hi Pratik,
On Wed, Mar 04, 2020 at 09:26:48PM +0530, Pratik Rajesh Sampat wrote:
> A concept patch in Skiboot to illustrate the case wherein handling of
> stop states for different DD versions of a CPU can be achieved by a
> simple modification in the list of cpu_features.
> As an example idle-stop1 is defined which uses P9_CPU_DD1 to define the
> cpu feature.
>
> Along with that, an implementation is being worked upon the LE OPAL
> series which helps OPAL handle the stop state entry and exit.
>
> This patch advertises this capability of the firmware which can be
> availed if the quirk-version-setting is not cognizable.
>
> The firmware-enabled stop is being worked by Abhishek Goel
> <huntbag@linux.vnet.ibm.com> building upon the LE OPAL series.
>
> Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com>
> ---
> core/cpufeatures.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/core/cpufeatures.c b/core/cpufeatures.c
> index ec30c975..b9875e7b 100644
> --- a/core/cpufeatures.c
> +++ b/core/cpufeatures.c
> @@ -510,6 +510,25 @@ static const struct cpu_feature cpu_features_table[] = {
> -1, -1, -1,
> NULL, },
>
> + /*
> + * QUIRK for ISAv3.0B stop idle instructions and registers
> + * Helps us determine if there are any quirks
> + * XXX: Same of idle-stop
> + */
> + { "idle-stop-v1",
> + CPU_P9_DD1,
> + ISA_V3_0B, USABLE_HV|USABLE_OS,
> + HV_CUSTOM, OS_CUSTOM,
> + -1, -1, -1,
> + NULL, },
So, at this point, we don't need any such quirk for any of the DD
version right ? This is to demonstrate that if say P9_DD1 had a quirk
w.r.t stop-state handling, then this is how we would advertise it to
the kernel.
> +
> + { "firmware-stop-supported",
> + CPU_P9,
> + ISA_V3_0B, USABLE_HV|USABLE_OS,
> + HV_CUSTOM, OS_CUSTOM,
> + -1, -1, -1,
> + NULL, },
> +
I suppose this is for the opal-cpuidle driver support posted here:
https://lists.ozlabs.org/pipermail/skiboot/2020-April/016726.html
> /*
> * ISAv3.0B Hypervisor Virtualization Interrupt
> * Also associated system registers, LPCR EE, HEIC, HVICE,
> @@ -883,6 +902,9 @@ static void add_cpufeatures(struct dt_node *cpus,
> const struct cpu_feature *f = &cpu_features_table[i];
>
> if (f->cpus_supported & cpu_feature_cpu) {
> + if (!strcmp(f->name, "firmware-stop-supported") &&
> + HAVE_BIG_ENDIAN)
> + continue;
In OPAL do we have an macro defining BIG_ENDIAN ? If yes, you could
wrap the "firmware-stop-supported" in cpu_features_table[] within
#ifndef BIG_ENDIAN. That way you won't need a special case here.
> DBG(" '%s'\n", f->name);
> add_cpu_feature_nodeps(features, f);
> }
> --
> 2.24.1
>
--
Thanks and Regards
gautham.
^ permalink raw reply
* [PATCH] i2c: powermac: Simplify reading the "reg" and "i2c-address" property
From: Aishwarya R @ 2020-04-08 10:03 UTC (permalink / raw)
Cc: Wolfram Sang, linux-kernel, Richard Fontana, Paul Mackerras,
Greg Kroah-Hartman, Thomas Gleixner, linuxppc-dev, aishwaryarj100,
linux-i2c
Use of_property_read_u32 to read the "reg" and "i2c-address" property
instead of using of_get_property to check the return values.
Signed-off-by: Aishwarya R <aishwaryarj100@gmail.com>
---
drivers/i2c/busses/i2c-powermac.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index d565714c1f13..81506c2dab65 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -207,18 +207,18 @@ static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
struct pmac_i2c_bus *bus,
struct device_node *node)
{
- const __be32 *prop;
- int len;
+ u32 prop;
+ int ret;
/* First check for valid "reg" */
- prop = of_get_property(node, "reg", &len);
- if (prop && (len >= sizeof(int)))
- return (be32_to_cpup(prop) & 0xff) >> 1;
+ ret = of_property_read_u32(node, "reg", &prop);
+ if (ret == 0)
+ return (prop & 0xff) >> 1;
/* Then check old-style "i2c-address" */
- prop = of_get_property(node, "i2c-address", &len);
- if (prop && (len >= sizeof(int)))
- return (be32_to_cpup(prop) & 0xff) >> 1;
+ ret = of_property_read_u32(node, "i2c-address", &prop);
+ if (ret == 0)
+ return (prop & 0xff) >> 1;
/* Now handle some devices with missing "reg" properties */
if (of_node_name_eq(node, "cereal"))
--
2.17.1
^ permalink raw reply related
* Re: [RFC 1/3] Interface for an idle-stop dependency structure
From: Gautham R Shenoy @ 2020-04-08 10:51 UTC (permalink / raw)
To: Pratik Rajesh Sampat
Cc: ego, mikey, pratik.r.sampat, vaidy, linux-kernel, npiggin,
linuxppc-dev, oohall, skiboot
In-Reply-To: <80c7a6ae66ab25bd088beaa3bd5c69f3b1352ac2.1583332695.git.psampat@linux.ibm.com>
Hi Pratik,
On Wed, Mar 04, 2020 at 09:31:21PM +0530, Pratik Rajesh Sampat wrote:
> Design patch to introduce the idea of having a dependency structure for
> idle-stop. The structure encapsulates the following:
> 1. Bitmask for version of idle-stop
> 2. Bitmask for propterties like ENABLE/DISABLE
> 3. Function pointer which helps handle how the stop must be invoked
>
> The commit lays a foundation for other idle-stop versions to be added
> and handled cleanly based on their specified requirments.
> Currently it handles the existing "idle-stop" version by setting the
> discovery bits and the function pointer.
So, if this patch is applied, and we are running with an OPAL that
doesn't publish the "idle-stop" dt-cpu-feature, then the goal is to
not enable any stop states. Is this correct ?
>
> Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com>
> ---
> arch/powerpc/include/asm/processor.h | 17 +++++++++++++++++
> arch/powerpc/kernel/dt_cpu_ftrs.c | 5 +++++
> arch/powerpc/platforms/powernv/idle.c | 17 +++++++++++++----
> drivers/cpuidle/cpuidle-powernv.c | 3 ++-
> 4 files changed, 37 insertions(+), 5 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
> index eedcbfb9a6ff..da59f01a5c09 100644
> --- a/arch/powerpc/include/asm/processor.h
> +++ b/arch/powerpc/include/asm/processor.h
> @@ -429,6 +429,23 @@ extern void power4_idle_nap(void);
> extern unsigned long cpuidle_disable;
> enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
>
> +#define STOP_ENABLE 0x00000001
> +
> +#define STOP_VERSION_P9 0x1
> +
> +/*
> + * Classify the dependencies of the stop states
> + * @idle_stop: function handler to handle the quirk stop version
> + * @cpuidle_prop: Signify support for stop states through kernel and/or firmware
> + * @stop_version: Classify quirk versions for stop states
> + */
> +typedef struct {
> + unsigned long (*idle_stop)(unsigned long, bool);
> + uint8_t cpuidle_prop;
> + uint8_t stop_version;
Why do we need both cpuidle_prop and stop_version ?
> +}stop_deps_t;
> +extern stop_deps_t stop_dep;
> +
> extern int powersave_nap; /* set if nap mode can be used in idle loop */
>
> extern void power7_idle_type(unsigned long type);
> diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
> index 182b4047c1ef..db1a525e090d 100644
> --- a/arch/powerpc/kernel/dt_cpu_ftrs.c
> +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
> @@ -292,6 +292,8 @@ static int __init feat_enable_idle_stop(struct dt_cpu_feature *f)
> lpcr |= LPCR_PECE1;
> lpcr |= LPCR_PECE2;
> mtspr(SPRN_LPCR, lpcr);
> + stop_dep.cpuidle_prop |= STOP_ENABLE;
> + stop_dep.stop_version = STOP_VERSION_P9;
Doesn't stop_version != 0 imply (stop_dep.cpuidle_prop & STOP_ENABLE)?
>
> return 1;
> }
> @@ -657,6 +659,9 @@ static void __init cpufeatures_setup_start(u32 isa)
> }
> }
>
> +stop_deps_t stop_dep = {NULL, 0x0, 0x0};
> +EXPORT_SYMBOL(stop_dep);
> +
> static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f)
> {
> const struct dt_cpu_feature_match *m;
> diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
> index 78599bca66c2..c32cdc37acf4 100644
> --- a/arch/powerpc/platforms/powernv/idle.c
> +++ b/arch/powerpc/platforms/powernv/idle.c
> @@ -812,7 +812,7 @@ static unsigned long power9_offline_stop(unsigned long psscr)
>
> #ifndef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> __ppc64_runlatch_off();
> - srr1 = power9_idle_stop(psscr, true);
> + srr1 = stop_dep.idle_stop(psscr, true);
> __ppc64_runlatch_on();
> #else
> /*
> @@ -828,7 +828,7 @@ static unsigned long power9_offline_stop(unsigned long psscr)
> local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_IDLE;
>
> __ppc64_runlatch_off();
> - srr1 = power9_idle_stop(psscr, false);
> + srr1 = stop_dep.idle_stop(psscr, true);
> __ppc64_runlatch_on();
>
> local_paca->kvm_hstate.hwthread_state = KVM_HWTHREAD_IN_KERNEL;
> @@ -856,7 +856,7 @@ void power9_idle_type(unsigned long stop_psscr_val,
> psscr = (psscr & ~stop_psscr_mask) | stop_psscr_val;
>
> __ppc64_runlatch_off();
> - srr1 = power9_idle_stop(psscr, true);
> + srr1 = stop_dep.idle_stop(psscr, true);
> __ppc64_runlatch_on();
>
There is one other place in arch/powerpc/kvm/book3s_hv_rmhandlers.S
where call isa300_idle_stop_mayloss (this is kvm_nap_sequence).
So, if stop states are not supported, then, KVM subsystem should know
about it. Some KVM configurations depend on putting the secondary
threads of the core offline into an idle state whose wakeup is from
0x100 vector. Your patch doesn't address that part.
> fini_irq_for_idle_irqsoff();
> @@ -1353,8 +1353,17 @@ static int __init pnv_init_idle_states(void)
> nr_pnv_idle_states = 0;
> supported_cpuidle_states = 0;
>
> - if (cpuidle_disable != IDLE_NO_OVERRIDE)
> + if (cpuidle_disable != IDLE_NO_OVERRIDE ||
> + !(stop_dep.cpuidle_prop & STOP_ENABLE))
This can be (stop_dep.stop_version == STOP_NOT_SUPPORTED) where
#define STOP_NOT_SUPPORTED 0
> goto out;
> + switch(stop_dep.stop_version) {
> + case STOP_VERSION_P9:
> + stop_dep.idle_stop = power9_idle_stop;
> + break;
> + default:
> + stop_dep.idle_stop = NULL;
You should add a pr_warn() here that stop state isn't supported
because the kernel doesn't know about the version.
> + goto out;
> + }
> rc = pnv_parse_cpuidle_dt();
> if (rc)
> return rc;
> diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c
> index 1b299e801f74..7430a8edf5c9 100644
> --- a/drivers/cpuidle/cpuidle-powernv.c
> +++ b/drivers/cpuidle/cpuidle-powernv.c
> @@ -371,7 +371,8 @@ static int powernv_add_idle_states(void)
> */
> static int powernv_idle_probe(void)
> {
> - if (cpuidle_disable != IDLE_NO_OVERRIDE)
> + if (cpuidle_disable != IDLE_NO_OVERRIDE ||
> + !(stop_dep.cpuidle_prop & STOP_ENABLE))
> return -ENODEV;
>
> if (firmware_has_feature(FW_FEATURE_OPAL)) {
> --
> 2.24.1
>
^ permalink raw reply
* Re: [RFC 3/3] Introduce capability for firmware-enabled-stop
From: Gautham R Shenoy @ 2020-04-08 10:54 UTC (permalink / raw)
To: Pratik Rajesh Sampat
Cc: ego, mikey, pratik.r.sampat, vaidy, linux-kernel, npiggin,
linuxppc-dev, oohall, skiboot
In-Reply-To: <55fa5021e4de901f05ded8b669777711bf2a9724.1583332695.git.psampat@linux.ibm.com>
Hi Pratik,
On Wed, Mar 04, 2020 at 09:31:23PM +0530, Pratik Rajesh Sampat wrote:
> Design patch that introduces the capability for firmware to handle the
> stop states instead. A bit is set based on the discovery of the feature
> and correspondingly also the responsibility to handle the stop states.
>
> The commit does not contain calling into the firmware to utilize
> firmware enabled stop.
>
> Signed-off-by: Pratik Rajesh Sampat <psampat at linux.ibm.com>
> ---
> arch/powerpc/include/asm/processor.h | 1 +
> arch/powerpc/kernel/dt_cpu_ftrs.c | 9 +++++++++
> 2 files changed, 10 insertions(+)
>
> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
> index 277dbabafd02..978fab35d133 100644
> --- a/arch/powerpc/include/asm/processor.h
> +++ b/arch/powerpc/include/asm/processor.h
> @@ -430,6 +430,7 @@ extern unsigned long cpuidle_disable;
> enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
>
> #define STOP_ENABLE 0x00000001
> +#define FIRMWARE_STOP_ENABLE 0x00000010
This could be made a bit in the "version" variable.
>
> #define STOP_VERSION_P9 0x1
> #define STOP_VERSION_P9_V1 0x2
> diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
> index 63e30aa49356..e00f8afabc46 100644
> --- a/arch/powerpc/kernel/dt_cpu_ftrs.c
> +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
> @@ -313,6 +313,14 @@ static int __init feat_enable_idle_stop_quirk(struct dt_cpu_feature *f)
>
> return 1;
> }
> +
> +static int __init feat_enable_firmware_stop(struct dt_cpu_feature *f)
> +{
> + stop_dep.cpuidle_prop |= FIRMWARE_STOP_ENABLE;
stop_dep.cpuidle_version |= FIRMWARE_STOP_V1; or some such
variant.
> +
> + return 1;
> +}
> +
> static int __init feat_enable_mmu_hash(struct dt_cpu_feature *f)
> {
> u64 lpcr;
> @@ -608,6 +616,7 @@ static struct dt_cpu_feature_match __initdata
> {"alignment-interrupt-dsisr", feat_enable_align_dsisr, 0},
> {"idle-stop", feat_enable_idle_stop, 0},
> {"idle-stop-v1", feat_enable_idle_stop_quirk, 0},
> + {"firmware-stop-supported", feat_enable_firmware_stop, 0},
> {"machine-check-power8", feat_enable_mce_power8, 0},
> {"performance-monitor-power8", feat_enable_pmu_power8, 0},
> {"data-stream-control-register", feat_enable_dscr, CPU_FTR_DSCR},
> --
> 2.24.1
>
^ permalink raw reply
* Re: [RFC PATCH 2/3] powerpc/lib: Initialize a temporary mm for code patching
From: Christophe Leroy @ 2020-04-08 11:01 UTC (permalink / raw)
To: Christopher M Riedl, linuxppc-dev
In-Reply-To: <1782990079.111623.1585624792778@privateemail.com>
Le 31/03/2020 à 05:19, Christopher M Riedl a écrit :
>> On March 24, 2020 11:10 AM Christophe Leroy <christophe.leroy@c-s.fr> wrote:
>>
>>
>> Le 23/03/2020 à 05:52, Christopher M. Riedl a écrit :
>>> When code patching a STRICT_KERNEL_RWX kernel the page containing the
>>> address to be patched is temporarily mapped with permissive memory
>>> protections. Currently, a per-cpu vmalloc patch area is used for this
>>> purpose. While the patch area is per-cpu, the temporary page mapping is
>>> inserted into the kernel page tables for the duration of the patching.
>>> The mapping is exposed to CPUs other than the patching CPU - this is
>>> undesirable from a hardening perspective.
>>>
>>> Use the `poking_init` init hook to prepare a temporary mm and patching
>>> address. Initialize the temporary mm by copying the init mm. Choose a
>>> randomized patching address inside the temporary mm userspace address
>>> portion. The next patch uses the temporary mm and patching address for
>>> code patching.
>>>
>>> Based on x86 implementation:
>>>
>>> commit 4fc19708b165
>>> ("x86/alternatives: Initialize temporary mm for patching")
>>>
>>> Signed-off-by: Christopher M. Riedl <cmr@informatik.wtf>
>>> ---
>>> arch/powerpc/lib/code-patching.c | 26 ++++++++++++++++++++++++++
>>> 1 file changed, 26 insertions(+)
>>>
>>> diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
>>> index 3345f039a876..18b88ecfc5a8 100644
>>> --- a/arch/powerpc/lib/code-patching.c
>>> +++ b/arch/powerpc/lib/code-patching.c
>>> @@ -11,6 +11,8 @@
>>> #include <linux/cpuhotplug.h>
>>> #include <linux/slab.h>
>>> #include <linux/uaccess.h>
>>> +#include <linux/sched/task.h>
>>> +#include <linux/random.h>
>>>
>>> #include <asm/pgtable.h>
>>> #include <asm/tlbflush.h>
>>> @@ -39,6 +41,30 @@ int raw_patch_instruction(unsigned int *addr, unsigned int instr)
>>> }
>>>
>>> #ifdef CONFIG_STRICT_KERNEL_RWX
>>> +
>>> +__ro_after_init struct mm_struct *patching_mm;
>>> +__ro_after_init unsigned long patching_addr;
>>
>> Can we make those those static ?
>>
>
> Yes, makes sense to me.
>
>>> +
>>> +void __init poking_init(void)
>>> +{
>>> + spinlock_t *ptl; /* for protecting pte table */
>>> + pte_t *ptep;
>>> +
>>> + patching_mm = copy_init_mm();
>>> + BUG_ON(!patching_mm);
>>
>> Does it needs to be a BUG_ON() ? Can't we fail gracefully with just a
>> WARN_ON ?
>>
>
> I'm not sure what failing gracefully means here? The main reason this could
> fail is if there is not enough memory to allocate the patching_mm. The
> previous implementation had this justification for BUG_ON():
But the system can continue running just fine after this failure.
Only the things that make use of code patching will fail (ftrace, kgdb, ...)
Checkpatch tells: "Avoid crashing the kernel - try using WARN_ON &
recovery code rather than BUG() or BUG_ON()"
All vital code patching has already been done previously, so I think a
WARN_ON() should be enough, plus returning non 0 to indicate that the
late_initcall failed.
>
> /*
> * Run as a late init call. This allows all the boot time patching to be done
> * simply by patching the code, and then we're called here prior to
> * mark_rodata_ro(), which happens after all init calls are run. Although
> * BUG_ON() is rude, in this case it should only happen if ENOMEM, and we judge
> * it as being preferable to a kernel that will crash later when someone tries
> * to use patch_instruction().
> */
> static int __init setup_text_poke_area(void)
> {
> BUG_ON(!cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
> "powerpc/text_poke:online", text_area_cpu_up,
> text_area_cpu_down));
>
> return 0;
> }
> late_initcall(setup_text_poke_area);
>
> I think the BUG_ON() is appropriate even if only to adhere to the previous
> judgement call. I can add a similar comment explaining the reasoning if
> that helps.
>
>>> +
>>> + /*
>>> + * In hash we cannot go above DEFAULT_MAP_WINDOW easily.
>>> + * XXX: Do we want additional bits of entropy for radix?
>>> + */
>>> + patching_addr = (get_random_long() & PAGE_MASK) %
>>> + (DEFAULT_MAP_WINDOW - PAGE_SIZE);
>>> +
>>> + ptep = get_locked_pte(patching_mm, patching_addr, &ptl);
>>> + BUG_ON(!ptep);
>>
>> Same here, can we fail gracefully instead ?
>>
>
> Same reasoning as above.
Here as well, a WARN_ON() should be enough, the system will continue
running after that.
>
>>> + pte_unmap_unlock(ptep, ptl);
>>> +}
>>> +
>>> static DEFINE_PER_CPU(struct vm_struct *, text_poke_area);
>>>
>>> static int text_area_cpu_up(unsigned int cpu)
>>>
>>
>> Christophe
Christophe
^ permalink raw reply
* Re: [RFC] cpuidle/powernv : Support for pre-entry and post exit of stop state in firmware
From: Gautham R Shenoy @ 2020-04-08 11:16 UTC (permalink / raw)
To: Abhishek Goel
Cc: ego, mikey, linux-kernel, npiggin, linuxppc-dev, oohall, psampat
In-Reply-To: <20200403092701.39751-1-huntbag@linux.vnet.ibm.com>
Hi Abhishek,
On Fri, Apr 03, 2020 at 04:27:01AM -0500, Abhishek Goel wrote:
> This patch provides kernel framework fro opal support of save restore
> of sprs in idle stop loop. Opal support for stop states is needed to
> selectively enable stop states or to introduce a quirk quickly in case
> a buggy stop state is present.
>
> We make a opal call from kernel if firmware-stop-support for stop
> states is present and enabled. All the quirks for pre-entry of stop
> state is handled inside opal. A call from opal is made into kernel
> where we execute stop afer saving of NVGPRs.
> After waking up from 0x100 vector in kernel, we enter back into opal.
> All the quirks in post exit path, if any, are then handled in opal,
> from where we return successfully back to kernel.
> For deep stop states in which additional SPRs are lost, saving and
> restoration will be done in OPAL.
>
> This idea was first proposed by Nick here:
> https://patchwork.ozlabs.org/patch/1208159/
>
> The corresponding skiboot patch for this kernel patch is here:
> https://patchwork.ozlabs.org/patch/1265959/
>
> When we callback from OPAL into kernel, r13 is clobbered. So, to
> access PACA we need to restore it from HSPRGO. In future we can
> handle this into OPAL as in here:
> https://patchwork.ozlabs.org/patch/1245275/
>
> Signed-off-by: Abhishek Goel <huntbag@linux.vnet.ibm.com>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> arch/powerpc/include/asm/opal-api.h | 8 ++++-
> arch/powerpc/include/asm/opal.h | 3 ++
> arch/powerpc/kernel/idle_book3s.S | 5 +++
> arch/powerpc/platforms/powernv/idle.c | 37 ++++++++++++++++++++++
> arch/powerpc/platforms/powernv/opal-call.c | 2 ++
> 5 files changed, 54 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
> index c1f25a760eb1..a2c782c99c9e 100644
> --- a/arch/powerpc/include/asm/opal-api.h
> +++ b/arch/powerpc/include/asm/opal-api.h
> @@ -214,7 +214,9 @@
> #define OPAL_SECVAR_GET 176
> #define OPAL_SECVAR_GET_NEXT 177
> #define OPAL_SECVAR_ENQUEUE_UPDATE 178
> -#define OPAL_LAST 178
> +#define OPAL_REGISTER_OS_OPS 181
> +#define OPAL_CPU_IDLE 182
> +#define OPAL_LAST 182
>
> #define QUIESCE_HOLD 1 /* Spin all calls at entry */
> #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */
> @@ -1181,6 +1183,10 @@ struct opal_mpipl_fadump {
> struct opal_mpipl_region region[];
> } __packed;
>
> +struct opal_os_ops {
> + __be64 os_idle_stop;
> +};
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* __OPAL_API_H */
> diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
> index 9986ac34b8e2..3c340bc4df8e 100644
> --- a/arch/powerpc/include/asm/opal.h
> +++ b/arch/powerpc/include/asm/opal.h
> @@ -400,6 +400,9 @@ void opal_powercap_init(void);
> void opal_psr_init(void);
> void opal_sensor_groups_init(void);
>
> +extern int64_t opal_register_os_ops(struct opal_os_ops *os_ops);
> +extern int64_t opal_cpu_idle(__be64 srr1_addr, uint64_t psscr);
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* _ASM_POWERPC_OPAL_H */
> diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
> index 22f249b6f58d..8d287d1d06c0 100644
> --- a/arch/powerpc/kernel/idle_book3s.S
> +++ b/arch/powerpc/kernel/idle_book3s.S
> @@ -49,6 +49,8 @@ _GLOBAL(isa300_idle_stop_noloss)
> */
> _GLOBAL(isa300_idle_stop_mayloss)
> mtspr SPRN_PSSCR,r3
> + mr r6, r13
> + mfspr r13, SPRN_HSPRG0
> std r1,PACAR1(r13)
> mflr r4
> mfcr r5
> @@ -74,6 +76,7 @@ _GLOBAL(isa300_idle_stop_mayloss)
> std r31,-8*18(r1)
> std r4,-8*19(r1)
> std r5,-8*20(r1)
> + std r6,-8*21(r1)
> /* 168 bytes */
> PPC_STOP
> b . /* catch bugs */
> @@ -91,8 +94,10 @@ _GLOBAL(idle_return_gpr_loss)
> ld r1,PACAR1(r13)
> ld r4,-8*19(r1)
> ld r5,-8*20(r1)
> + ld r6,-8*21(r1)
> mtlr r4
> mtcr r5
> + mr r13,r6
> /*
> * KVM nap requires r2 to be saved, rather than just restoring it
> * from PACATOC. This could be avoided for that less common case
> diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
> index 78599bca66c2..1841027b25c5 100644
> --- a/arch/powerpc/platforms/powernv/idle.c
> +++ b/arch/powerpc/platforms/powernv/idle.c
> @@ -35,6 +35,7 @@
> static u32 supported_cpuidle_states;
> struct pnv_idle_states_t *pnv_idle_states;
> int nr_pnv_idle_states;
> +static bool firmware_stop_supported;
>
> /*
> * The default stop state that will be used by ppc_md.power_save
> @@ -602,6 +603,25 @@ struct p9_sprs {
> u64 uamor;
> };
>
> +/*
> + * This function is called from OPAL if firmware support for stop
> + * states is present and enabled. It provides a fallback for idle
> + * stop states via OPAL.
> + */
> +static uint64_t os_idle_stop(uint64_t psscr, bool save_gprs)
"save_gprs" can be guessed from the psscr ESL|EC bits. But I guess
there is no harm in obtaining this explicitly from OPAL.
> +{
> + /*
> + * For lite state which does not lose even GPRS we call
> + * idle_stop_noloss while for all other states we call
> + * idle_stop_mayloss. Saving and restoration of other additional
> + * SPRs if required is handled in OPAL. All the quirks are also
> + * handled in OPAL.
> + */
> + if (!save_gprs)
> + return isa300_idle_stop_noloss(psscr);
> + return isa300_idle_stop_mayloss(psscr);
> +}
> +
> static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
> {
> int cpu = raw_smp_processor_id();
> @@ -613,6 +633,16 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
> unsigned long mmcr0 = 0;
> struct p9_sprs sprs = {}; /* avoid false used-uninitialised */
> bool sprs_saved = false;
> + int rc = 0;
> +
> + /*
> + * Kernel takes decision whether to make OPAL call or not. This logic
> + * will be combined with the logic for BE opal to take decision.
> + */
> + if (firmware_stop_supported) {
> + rc = opal_cpu_idle(cpu_to_be64(__pa(&srr1)), (uint64_t) psscr);
> + goto out;
> + }
Well, we should choose the opal route only if kernel does not know
about the stop version, in which case OPAL based driver is a
fallback. In your implementation, OPAL based driver seems to be the
first choice. We can eventually go there, once we have the capability
to run OPAL with mmu_on, with no RFID overhead. Until then, we should
let the kernel handle stop state entry/exit as long as it knows about
the version.
>
> if (!(psscr & (PSSCR_EC|PSSCR_ESL))) {
> /* EC=ESL=0 case */
> @@ -1232,6 +1262,10 @@ static int pnv_parse_cpuidle_dt(void)
> pr_warn("opal: PowerMgmt Node not found\n");
> return -ENODEV;
> }
> +
> + if (of_device_is_compatible(np, "firmware-stop-supported"))
> + firmware_stop_supported = true;
> +
> nr_idle_states = of_property_count_u32_elems(np,
> "ibm,cpu-idle-state-flags");
>
> @@ -1326,6 +1360,7 @@ static int pnv_parse_cpuidle_dt(void)
>
> static int __init pnv_init_idle_states(void)
> {
> + struct opal_os_ops os_ops;
> int cpu;
> int rc = 0;
>
> @@ -1349,6 +1384,8 @@ static int __init pnv_init_idle_states(void)
> }
> }
>
> + os_ops.os_idle_stop = be64_to_cpu(os_idle_stop);
> + rc = opal_register_os_ops((struct opal_os_ops *)(&os_ops));
> /* In case we error out nr_pnv_idle_states will be zero */
> nr_pnv_idle_states = 0;
> supported_cpuidle_states = 0;
> diff --git a/arch/powerpc/platforms/powernv/opal-call.c b/arch/powerpc/platforms/powernv/opal-call.c
> index 5cd0f52d258f..c885e607ba62 100644
> --- a/arch/powerpc/platforms/powernv/opal-call.c
> +++ b/arch/powerpc/platforms/powernv/opal-call.c
> @@ -293,3 +293,5 @@ OPAL_CALL(opal_mpipl_query_tag, OPAL_MPIPL_QUERY_TAG);
> OPAL_CALL(opal_secvar_get, OPAL_SECVAR_GET);
> OPAL_CALL(opal_secvar_get_next, OPAL_SECVAR_GET_NEXT);
> OPAL_CALL(opal_secvar_enqueue_update, OPAL_SECVAR_ENQUEUE_UPDATE);
> +OPAL_CALL(opal_register_os_ops, OPAL_REGISTER_OS_OPS);
> +OPAL_CALL(opal_cpu_idle, OPAL_CPU_IDLE);
> --
> 2.17.1
>
^ permalink raw reply
* [PATCH] powerpc/powernv: Add a print indicating when an IODA PE is released
From: Oliver O'Halloran @ 2020-04-08 11:22 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Oliver O'Halloran
Quite useful to know in some cases.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 3d81c01..82e5098 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -3475,6 +3475,8 @@ static void pnv_ioda_release_pe(struct pnv_ioda_pe *pe)
struct pnv_phb *phb = pe->phb;
struct pnv_ioda_pe *slave, *tmp;
+ pe_info(pe, "Releasing PE\n");
+
mutex_lock(&phb->ioda.pe_list_mutex);
list_del(&pe->list);
mutex_unlock(&phb->ioda.pe_list_mutex);
--
2.9.5
^ permalink raw reply related
* Re: [PATCH v2] powerpc/ptrace: Do not return ENOSYS if invalid syscall
From: Michael Ellerman @ 2020-04-08 11:40 UTC (permalink / raw)
To: Thadeu Lima de Souza Cascardo, linuxppc-dev
Cc: Thadeu Lima de Souza Cascardo, Kees Cook
In-Reply-To: <20200329175957.24264-1-cascardo@canonical.com>
Hi Cascardo,
Thanks for following-up on this.
Unfortunately I don't think I can merge this fix.
Thadeu Lima de Souza Cascardo <cascardo@canonical.com> writes:
> If a tracer sets the syscall number to an invalid one, allow the return
> value set by the tracer to be returned the tracee.
The problem is this patch not only *allows* the tracer to set the return
value, but it also *requires* the tracer to set the return value. That
would be a change to the ABI.
Currently if a tracer sets the syscall number to -1, that's all they
need to do, and the kernel will make sure ENOSYS is returned to the
tracee.
With this patch applied the tracer can set the syscall to -1 but they
also must set the return value explicitly. Otherwise the syscall will
just return with whatever value happens to be in r3.
I confirmed this patch breaks the strace testsuite:
# cd strace/tests/
# bash qual_inject-retval.test
../../strace: Failed to tamper with process 13301: unexpectedly got no error (return value 0x10001090, error 0)
expected retval 0, got retval 268439696
chdir("..") = 268439696 (INJECTED)
+++ exited with 1 +++
qual_inject-retval.test: failed test: ../../strace -a12 -echdir -einject=chdir:retval=0 ../qual_inject-retval 0 failed with code 1
The return value 0x10001090 is the address of the ".." string passed to
the syscall.
> The test for NR_syscalls is already at entry_64.S, and it's at
> do_syscall_trace_enter only to skip audit and trace.
>
> After this, two failures from seccomp_bpf selftests complete just fine,
> as the failing test was using ptrace to change the syscall to return an
> error or a fake value, but were failing as it was always returning
> -ENOSYS.
This test wants to change the syscall number and the return value, and
do both from the syscall enter hook.
We don't support that, because we have no way of knowing if the tracer
set the return value, so we always return ENOSYS. Our ptrace ABI has
been that way forever.
We could possibly do something like compare r3 and orig_gpr3 and assume
that if they're different then the tracer has set r3 to the return
value. But I worry that will break something and/or just be very subtle
and bug prone.
I think the right way to fix it is for the test case to change the
return value from the syscall exit hook. That will work on all existing
kernels AFAIK. It's also what strace does.
cheers
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index 25c0424e8868..557ae4bc2331 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -3314,7 +3314,7 @@ long do_syscall_trace_enter(struct pt_regs *regs)
>
> /* Avoid trace and audit when syscall is invalid. */
> if (regs->gpr[0] >= NR_syscalls)
> - goto skip;
> + return regs->gpr[0];
>
> if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
> trace_sys_enter(regs, regs->gpr[0]);
^ permalink raw reply
* Re: [PATCH v2 0/2] Don't generate thousands of new warnings when building docs
From: Mauro Carvalho Chehab @ 2020-04-08 11:40 UTC (permalink / raw)
To: Michael Ellerman
Cc: Ricardo Ribalda Delgado, Linux Doc Mailing List, target-devel,
Paul Mackerras, H. Peter Anvin, Alex Shi, linux-scsi,
Jonathan Corbet, x86, Tyler Hicks, Ingo Molnar, Jakub Kicinski,
Jacopo Mondi, Luca Ceresoli, Johannes Berg, ecryptfs,
Matthias Maennich, dmaengine, Borislav Petkov, Thomas Gleixner,
Martin K. Petersen, netdev, linux-kernel, Vinod Koul, Harry Wei,
Greg Kroah-Hartman, Hans Verkuil, linuxppc-dev, David S. Miller,
Madhuparna Bhowmik
In-Reply-To: <87lfn8klf4.fsf@mpe.ellerman.id.au>
Em Tue, 07 Apr 2020 13:46:23 +1000
Michael Ellerman <mpe@ellerman.id.au> escreveu:
> Mauro Carvalho Chehab <mchehab+huawei@kernel.org> writes:
> > This small series address a regression caused by a new patch at
> > docs-next (and at linux-next).
> >
...
> > This solves almost all problems we have. Still, there are a few places
> > where we have two chapters at the same document with the
> > same name. The first patch addresses this problem.
>
> I'm still seeing a lot of warnings. Am I doing something wrong?
>
> cheers
>
> /linux/Documentation/powerpc/cxl.rst:406: WARNING: duplicate label powerpc/cxl:open, other instance in /linux/Documentation/powerpc/cxl.rst
...
> /linux/Documentation/powerpc/syscall64-abi.rst:86: WARNING: duplicate label powerpc/syscall64-abi:parameters and return value, other instance in /linux/Documentation/powerpc/syscall64-abi.rst
...
> /linux/Documentation/powerpc/ultravisor.rst:339: WARNING: duplicate label powerpc/ultravisor:syntax, other instance in /linux/Documentation/powerpc/ultravisor.rst
...
I can't reproduce your issue here at linux-next (+ my pending doc patches).
So, I can only provide you some hints.
If you see the logs you posted, all of them are related to duplicated
labels inside the same file.
-
The new Sphinx module we're using (sphinx.ext.autosectionlabel) generates
references for two levels, within the same document file (after this patch).
Looking at the first document (at linux-next version), it has:
1) A first level document title:
Coherent Accelerator Interface (CXL)
2) Several second level titles:
Introduction
Hardware overview
AFU Modes
MMIO space
Interrupts
Work Element Descriptor (WED)
User API
Sysfs Class
Udev rules
Right now, there's no duplication, but if someone adds, for example,
another first-level or second-level title called "Interrupts", then
the file will produce a duplicated label and Sphinx will warn.
The same would happen if someone adds another title (either first
level or second level) called "Coherent Accelerator Interface (CXL)",
as this will conflict with the document title.
-
Now, if the title "Coherent Accelerator Interface (CXL)" got removed,
then "Introduction".."Udev rules" will become first level titles.
Then, the sections at the "User API": "open", "ioctl"... will become
second level titles and it will produce lots of warnings.
-
That's said, IMHO, this document needs section titles for the two
sections under "User API". Adding it would allow removing the document
title. See enclosed.
Thanks,
Mauro
powerpc: docs: cxl.rst: mark two section titles as such
The User API chapter contains two sub-chapters. Mark them as
such.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
diff --git a/Documentation/powerpc/cxl.rst b/Documentation/powerpc/cxl.rst
index 920546d81326..d2d77057610e 100644
--- a/Documentation/powerpc/cxl.rst
+++ b/Documentation/powerpc/cxl.rst
@@ -133,6 +133,7 @@ User API
========
1. AFU character devices
+^^^^^^^^^^^^^^^^^^^^^^^^
For AFUs operating in AFU directed mode, two character device
files will be created. /dev/cxl/afu0.0m will correspond to a
@@ -395,6 +396,7 @@ read
2. Card character device (powerVM guest only)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In a powerVM guest, an extra character device is created for the
card. The device is only used to write (flash) a new image on the
^ permalink raw reply related
* decruft the vmalloc API
From: Christoph Hellwig @ 2020-04-08 11:58 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
Hi all,
Peter noticed that with some dumb luck you can toast the kernel address
space with exported vmalloc symbols.
I used this as an opportunity to decruft the vmalloc.c API and make it
much more systematic. This also removes any chance to create vmalloc
mappings outside the designated areas or using executable permissions
from modules. Besides that it removes more than 300 lines of code.
A git tree is also available here:
git://git.infradead.org/users/hch/misc.git sanitize-vmalloc-api
Gitweb:
http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/sanitize-vmalloc-api
^ permalink raw reply
* [PATCH 01/28] x86/hyperv: use vmalloc_exec for the hypercall page
From: Christoph Hellwig @ 2020-04-08 11:58 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
Use the designated helper for allocating executable kernel memory, and
remove the now unused PAGE_KERNEL_RX define.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/x86/hyperv/hv_init.c | 2 +-
arch/x86/include/asm/pgtable_types.h | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index b0da5320bcff..5a4b363ba67b 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -355,7 +355,7 @@ void __init hyperv_init(void)
guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
- hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
+ hv_hypercall_pg = vmalloc_exec(PAGE_SIZE);
if (hv_hypercall_pg == NULL) {
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
goto remove_cpuhp_state;
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index b6606fe6cfdf..947867f112ea 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -194,7 +194,6 @@ enum page_cache_mode {
#define _PAGE_TABLE_NOENC (__PP|__RW|_USR|___A| 0|___D| 0| 0)
#define _PAGE_TABLE (__PP|__RW|_USR|___A| 0|___D| 0| 0| _ENC)
#define __PAGE_KERNEL_RO (__PP| 0| 0|___A|__NX|___D| 0|___G)
-#define __PAGE_KERNEL_RX (__PP| 0| 0|___A| 0|___D| 0|___G)
#define __PAGE_KERNEL_NOCACHE (__PP|__RW| 0|___A|__NX|___D| 0|___G| __NC)
#define __PAGE_KERNEL_VVAR (__PP| 0|_USR|___A|__NX|___D| 0|___G)
#define __PAGE_KERNEL_LARGE (__PP|__RW| 0|___A|__NX|___D|_PSE|___G)
@@ -220,7 +219,6 @@ enum page_cache_mode {
#define PAGE_KERNEL_RO __pgprot_mask(__PAGE_KERNEL_RO | _ENC)
#define PAGE_KERNEL_EXEC __pgprot_mask(__PAGE_KERNEL_EXEC | _ENC)
#define PAGE_KERNEL_EXEC_NOENC __pgprot_mask(__PAGE_KERNEL_EXEC | 0)
-#define PAGE_KERNEL_RX __pgprot_mask(__PAGE_KERNEL_RX | _ENC)
#define PAGE_KERNEL_NOCACHE __pgprot_mask(__PAGE_KERNEL_NOCACHE | _ENC)
#define PAGE_KERNEL_LARGE __pgprot_mask(__PAGE_KERNEL_LARGE | _ENC)
#define PAGE_KERNEL_LARGE_EXEC __pgprot_mask(__PAGE_KERNEL_LARGE_EXEC | _ENC)
--
2.25.1
^ permalink raw reply related
* [PATCH 02/28] staging: android: ion: use vmap instead of vm_map_ram
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
vm_map_ram can keep mappings around after the vm_unmap_ram. Using that
with non-PAGE_KERNEL mappings can lead to all kinds of aliasing issues.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/staging/android/ion/ion_heap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index 473b465724f1..a2d5c6df4b96 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -99,12 +99,12 @@ int ion_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
static int ion_heap_clear_pages(struct page **pages, int num, pgprot_t pgprot)
{
- void *addr = vm_map_ram(pages, num, -1, pgprot);
+ void *addr = vmap(pages, num, VM_MAP);
if (!addr)
return -ENOMEM;
memset(addr, 0, PAGE_SIZE * num);
- vm_unmap_ram(addr, num);
+ vunmap(addr);
return 0;
}
--
2.25.1
^ permalink raw reply related
* [PATCH 03/28] staging: media: ipu3: use vmap insted of reimplementing it
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
Just use vmap instead of messing with vmalloc internals.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/staging/media/ipu3/ipu3-css-pool.h | 4 +--
drivers/staging/media/ipu3/ipu3-dmamap.c | 30 ++++++----------------
2 files changed, 9 insertions(+), 25 deletions(-)
diff --git a/drivers/staging/media/ipu3/ipu3-css-pool.h b/drivers/staging/media/ipu3/ipu3-css-pool.h
index f4a60b41401b..a8ccd4f70320 100644
--- a/drivers/staging/media/ipu3/ipu3-css-pool.h
+++ b/drivers/staging/media/ipu3/ipu3-css-pool.h
@@ -15,14 +15,12 @@ struct imgu_device;
* @size: size of the buffer in bytes.
* @vaddr: kernel virtual address.
* @daddr: iova dma address to access IPU3.
- * @vma: private, a pointer to &struct vm_struct,
- * used for imgu_dmamap_free.
*/
struct imgu_css_map {
size_t size;
void *vaddr;
dma_addr_t daddr;
- struct vm_struct *vma;
+ struct page **pages;
};
/**
diff --git a/drivers/staging/media/ipu3/ipu3-dmamap.c b/drivers/staging/media/ipu3/ipu3-dmamap.c
index 7431322379f6..8a19b0024152 100644
--- a/drivers/staging/media/ipu3/ipu3-dmamap.c
+++ b/drivers/staging/media/ipu3/ipu3-dmamap.c
@@ -96,6 +96,7 @@ void *imgu_dmamap_alloc(struct imgu_device *imgu, struct imgu_css_map *map,
unsigned long shift = iova_shift(&imgu->iova_domain);
struct device *dev = &imgu->pci_dev->dev;
size_t size = PAGE_ALIGN(len);
+ int count = size >> PAGE_SHIFT;
struct page **pages;
dma_addr_t iovaddr;
struct iova *iova;
@@ -114,7 +115,7 @@ void *imgu_dmamap_alloc(struct imgu_device *imgu, struct imgu_css_map *map,
/* Call IOMMU driver to setup pgt */
iovaddr = iova_dma_addr(&imgu->iova_domain, iova);
- for (i = 0; i < size / PAGE_SIZE; ++i) {
+ for (i = 0; i < count; ++i) {
rval = imgu_mmu_map(imgu->mmu, iovaddr,
page_to_phys(pages[i]), PAGE_SIZE);
if (rval)
@@ -123,33 +124,23 @@ void *imgu_dmamap_alloc(struct imgu_device *imgu, struct imgu_css_map *map,
iovaddr += PAGE_SIZE;
}
- /* Now grab a virtual region */
- map->vma = __get_vm_area(size, VM_USERMAP, VMALLOC_START, VMALLOC_END);
- if (!map->vma)
+ map->vaddr = vmap(pages, count, VM_USERMAP, PAGE_KERNEL);
+ if (!map->vaddr)
goto out_unmap;
- map->vma->pages = pages;
- /* And map it in KVA */
- if (map_vm_area(map->vma, PAGE_KERNEL, pages))
- goto out_vunmap;
-
+ map->pages = pages;
map->size = size;
map->daddr = iova_dma_addr(&imgu->iova_domain, iova);
- map->vaddr = map->vma->addr;
dev_dbg(dev, "%s: allocated %zu @ IOVA %pad @ VA %p\n", __func__,
- size, &map->daddr, map->vma->addr);
-
- return map->vma->addr;
+ size, &map->daddr, map->vaddr);
-out_vunmap:
- vunmap(map->vma->addr);
+ return map->vaddr;
out_unmap:
imgu_dmamap_free_buffer(pages, size);
imgu_mmu_unmap(imgu->mmu, iova_dma_addr(&imgu->iova_domain, iova),
i * PAGE_SIZE);
- map->vma = NULL;
out_free_iova:
__free_iova(&imgu->iova_domain, iova);
@@ -177,8 +168,6 @@ void imgu_dmamap_unmap(struct imgu_device *imgu, struct imgu_css_map *map)
*/
void imgu_dmamap_free(struct imgu_device *imgu, struct imgu_css_map *map)
{
- struct vm_struct *area = map->vma;
-
dev_dbg(&imgu->pci_dev->dev, "%s: freeing %zu @ IOVA %pad @ VA %p\n",
__func__, map->size, &map->daddr, map->vaddr);
@@ -187,11 +176,8 @@ void imgu_dmamap_free(struct imgu_device *imgu, struct imgu_css_map *map)
imgu_dmamap_unmap(imgu, map);
- if (WARN_ON(!area) || WARN_ON(!area->pages))
- return;
-
- imgu_dmamap_free_buffer(area->pages, map->size);
vunmap(map->vaddr);
+ imgu_dmamap_free_buffer(map->pages, map->size);
map->vaddr = NULL;
}
--
2.25.1
^ permalink raw reply related
* [PATCH 04/28] dma-mapping: use vmap insted of reimplementing it
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
Replace the open coded instance of vmap with the actual function. In
the non-contiguous (IOMMU) case this requires an extra find_vm_area,
but given that this isn't a fast path function that is a small price
to pay.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
kernel/dma/remap.c | 48 ++++++++++++----------------------------------
1 file changed, 12 insertions(+), 36 deletions(-)
diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index d14cbc83986a..7a8ba60951e8 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -20,23 +20,6 @@ struct page **dma_common_find_pages(void *cpu_addr)
return area->pages;
}
-static struct vm_struct *__dma_common_pages_remap(struct page **pages,
- size_t size, pgprot_t prot, const void *caller)
-{
- struct vm_struct *area;
-
- area = get_vm_area_caller(size, VM_DMA_COHERENT, caller);
- if (!area)
- return NULL;
-
- if (map_vm_area(area, prot, pages)) {
- vunmap(area->addr);
- return NULL;
- }
-
- return area;
-}
-
/*
* Remaps an array of PAGE_SIZE pages into another vm_area.
* Cannot be used in non-sleeping contexts
@@ -44,15 +27,12 @@ static struct vm_struct *__dma_common_pages_remap(struct page **pages,
void *dma_common_pages_remap(struct page **pages, size_t size,
pgprot_t prot, const void *caller)
{
- struct vm_struct *area;
+ void *vaddr;
- area = __dma_common_pages_remap(pages, size, prot, caller);
- if (!area)
- return NULL;
-
- area->pages = pages;
-
- return area->addr;
+ vaddr = vmap(pages, count, VM_DMA_COHERENT, prot);
+ if (vaddr)
+ find_vm_area(vaddr)->pages = pages;
+ return vaddr;
}
/*
@@ -62,24 +42,20 @@ void *dma_common_pages_remap(struct page **pages, size_t size,
void *dma_common_contiguous_remap(struct page *page, size_t size,
pgprot_t prot, const void *caller)
{
- int i;
+ int count = size >> PAGE_SHIFT;
struct page **pages;
- struct vm_struct *area;
+ void *vaddr;
+ int i;
- pages = kmalloc(sizeof(struct page *) << get_order(size), GFP_KERNEL);
+ pages = kmalloc_array(count, sizeof(struct page *), GFP_KERNEL);
if (!pages)
return NULL;
-
- for (i = 0; i < (size >> PAGE_SHIFT); i++)
+ for (i = 0; i < count; i++)
pages[i] = nth_page(page, i);
-
- area = __dma_common_pages_remap(pages, size, prot, caller);
-
+ vaddr = vmap(pages, count, VM_DMA_COHERENT, prot);
kfree(pages);
- if (!area)
- return NULL;
- return area->addr;
+ return vaddr;
}
/*
--
2.25.1
^ permalink raw reply related
* [PATCH 06/28] powerpc: remove __ioremap_at and __iounmap_at
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
These helpers are only used for remapping the ISA I/O base. Replace
the mapping side with a remap_isa_range helper in isa-bridge.c that
hard codes all the known arguments, and just remove __iounmap_at in
favour of open coding it in the only caller.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/powerpc/include/asm/io.h | 8 -----
arch/powerpc/kernel/isa-bridge.c | 28 +++++++++++++-----
arch/powerpc/mm/ioremap_64.c | 50 --------------------------------
3 files changed, 21 insertions(+), 65 deletions(-)
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 71f1c5d69839..4fdbb9e45dd7 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -699,10 +699,6 @@ static inline void iosync(void)
*
* * iounmap undoes such a mapping and can be hooked
*
- * * __ioremap_at (and the pending __iounmap_at) are low level functions to
- * create hand-made mappings for use only by the PCI code and cannot
- * currently be hooked. Must be page aligned.
- *
* * __ioremap_caller is the same as above but takes an explicit caller
* reference rather than using __builtin_return_address(0)
*
@@ -729,10 +725,6 @@ void __iomem *do_ioremap(phys_addr_t pa, phys_addr_t offset, unsigned long size,
extern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size,
pgprot_t prot, void *caller);
-extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea,
- unsigned long size, pgprot_t prot);
-extern void __iounmap_at(void *ea, unsigned long size);
-
/*
* When CONFIG_PPC_INDIRECT_PIO is set, we use the generic iomap implementation
* which needs some additional definitions here. They basically allow PIO
diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
index 773671b512df..2257d24e6a26 100644
--- a/arch/powerpc/kernel/isa-bridge.c
+++ b/arch/powerpc/kernel/isa-bridge.c
@@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/notifier.h>
+#include <linux/vmalloc.h>
#include <asm/processor.h>
#include <asm/io.h>
@@ -38,6 +39,22 @@ EXPORT_SYMBOL_GPL(isa_bridge_pcidev);
#define ISA_SPACE_MASK 0x1
#define ISA_SPACE_IO 0x1
+static void remap_isa_base(phys_addr_t pa, unsigned long size)
+{
+ WARN_ON_ONCE(ISA_IO_BASE & ~PAGE_MASK);
+ WARN_ON_ONCE(pa & ~PAGE_MASK);
+ WARN_ON_ONCE(size & ~PAGE_MASK);
+
+ if (slab_is_available()) {
+ if (ioremap_page_range(ISA_IO_BASE, ISA_IO_BASE + size, pa,
+ pgprot_noncached(PAGE_KERNEL)))
+ unmap_kernel_range(ISA_IO_BASE, size);
+ } else {
+ early_ioremap_range(ISA_IO_BASE, pa, size,
+ pgprot_noncached(PAGE_KERNEL));
+ }
+}
+
static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
unsigned long phb_io_base_phys)
{
@@ -105,15 +122,13 @@ static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
if (size > 0x10000)
size = 0x10000;
- __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
- size, pgprot_noncached(PAGE_KERNEL));
+ remap_isa_base(phb_io_base_phys, size);
return;
inval_range:
printk(KERN_ERR "no ISA IO ranges or unexpected isa range, "
"mapping 64k\n");
- __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
- 0x10000, pgprot_noncached(PAGE_KERNEL));
+ remap_isa_base(phb_io_base_phys, 0x10000);
}
@@ -248,8 +263,7 @@ void __init isa_bridge_init_non_pci(struct device_node *np)
* and map it
*/
isa_io_base = ISA_IO_BASE;
- __ioremap_at(pbase, (void *)ISA_IO_BASE,
- size, pgprot_noncached(PAGE_KERNEL));
+ remap_isa_base(pbase, size);
pr_debug("ISA: Non-PCI bridge is %pOF\n", np);
}
@@ -297,7 +311,7 @@ static void isa_bridge_remove(void)
isa_bridge_pcidev = NULL;
/* Unmap the ISA area */
- __iounmap_at((void *)ISA_IO_BASE, 0x10000);
+ unmap_kernel_range(ISA_IO_BASE, 0x10000);
}
/**
diff --git a/arch/powerpc/mm/ioremap_64.c b/arch/powerpc/mm/ioremap_64.c
index 50a99d9684f7..ba5cbb0d66bd 100644
--- a/arch/powerpc/mm/ioremap_64.c
+++ b/arch/powerpc/mm/ioremap_64.c
@@ -4,56 +4,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
-/**
- * Low level function to establish the page tables for an IO mapping
- */
-void __iomem *__ioremap_at(phys_addr_t pa, void *ea, unsigned long size, pgprot_t prot)
-{
- int ret;
- unsigned long va = (unsigned long)ea;
-
- /* We don't support the 4K PFN hack with ioremap */
- if (pgprot_val(prot) & H_PAGE_4K_PFN)
- return NULL;
-
- if ((ea + size) >= (void *)IOREMAP_END) {
- pr_warn("Outside the supported range\n");
- return NULL;
- }
-
- WARN_ON(pa & ~PAGE_MASK);
- WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
- WARN_ON(size & ~PAGE_MASK);
-
- if (slab_is_available()) {
- ret = ioremap_page_range(va, va + size, pa, prot);
- if (ret)
- unmap_kernel_range(va, size);
- } else {
- ret = early_ioremap_range(va, pa, size, prot);
- }
-
- if (ret)
- return NULL;
-
- return (void __iomem *)ea;
-}
-EXPORT_SYMBOL(__ioremap_at);
-
-/**
- * Low level function to tear down the page tables for an IO mapping. This is
- * used for mappings that are manipulated manually, like partial unmapping of
- * PCI IOs or ISA space.
- */
-void __iounmap_at(void *ea, unsigned long size)
-{
- WARN_ON(((unsigned long)ea) & ~PAGE_MASK);
- WARN_ON(size & ~PAGE_MASK);
-
- unmap_kernel_range((unsigned long)ea, size);
-}
-EXPORT_SYMBOL(__iounmap_at);
-
void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size,
pgprot_t prot, void *caller)
{
--
2.25.1
^ permalink raw reply related
* [PATCH 05/28] powerpc: add an ioremap_phb helper
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
Factor code shared between pci_64 and electra_cf into a ioremap_pbh
helper that follows the normal ioremap semantics, and returns a
useful __iomem pointer. Note that it opencodes __ioremap_at as
we know from the callers the slab is available. Switch pci_64
to also store the result as __iomem pointer, and unmap the result
using iounmap instead of force casting and using vmalloc APIs.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/powerpc/include/asm/io.h | 2 +
arch/powerpc/include/asm/pci-bridge.h | 2 +-
arch/powerpc/kernel/pci_64.c | 53 ++++++++++++++++++---------
drivers/pcmcia/electra_cf.c | 45 ++++++++---------------
4 files changed, 54 insertions(+), 48 deletions(-)
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 635969b5b58e..71f1c5d69839 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -719,6 +719,8 @@ void __iomem *ioremap_coherent(phys_addr_t address, unsigned long size);
extern void iounmap(volatile void __iomem *addr);
+void __iomem *ioremap_pbh(phys_addr_t paddr, unsigned long size);
+
int early_ioremap_range(unsigned long ea, phys_addr_t pa,
unsigned long size, pgprot_t prot);
void __iomem *do_ioremap(phys_addr_t pa, phys_addr_t offset, unsigned long size,
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 69f4cb3b7c56..b92e81b256e5 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -66,7 +66,7 @@ struct pci_controller {
void __iomem *io_base_virt;
#ifdef CONFIG_PPC64
- void *io_base_alloc;
+ void __iomem *io_base_alloc;
#endif
resource_size_t io_base_phys;
resource_size_t pci_io_size;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index f83d1f69b1dd..8e86bd9c1eca 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -109,23 +109,46 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
/* Get the host bridge */
hose = pci_bus_to_host(bus);
- /* Check if we have IOs allocated */
- if (hose->io_base_alloc == NULL)
- return 0;
-
pr_debug("IO unmapping for PHB %pOF\n", hose->dn);
pr_debug(" alloc=0x%p\n", hose->io_base_alloc);
- /* This is a PHB, we fully unmap the IO area */
- vunmap(hose->io_base_alloc);
-
+ iounmap(hose->io_base_alloc);
return 0;
}
EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
-static int pcibios_map_phb_io_space(struct pci_controller *hose)
+void __iomem *ioremap_pbh(phys_addr_t paddr, unsigned long size)
{
struct vm_struct *area;
+ unsigned long addr;
+
+ WARN_ON_ONCE(paddr & ~PAGE_MASK);
+ WARN_ON_ONCE(size & ~PAGE_MASK);
+
+ /*
+ * Let's allocate some IO space for that guy. We don't pass VM_IOREMAP
+ * because we don't care about alignment tricks that the core does in
+ * that case. Maybe we should due to stupid card with incomplete
+ * address decoding but I'd rather not deal with those outside of the
+ * reserved 64K legacy region.
+ */
+ area = __get_vm_area(size, 0, PHB_IO_BASE, PHB_IO_END);
+ if (!area)
+ return NULL;
+
+ addr = (unsigned long)area->addr;
+ if (ioremap_page_range(addr, addr + size, paddr,
+ pgprot_noncached(PAGE_KERNEL))) {
+ unmap_kernel_range(addr, size);
+ return NULL;
+ }
+
+ return (void __iomem *)addr;
+}
+EXPORT_SYMBOL_GPL(ioremap_pbh);
+
+static int pcibios_map_phb_io_space(struct pci_controller *hose)
+{
unsigned long phys_page;
unsigned long size_page;
unsigned long io_virt_offset;
@@ -146,12 +169,11 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose)
* with incomplete address decoding but I'd rather not deal with
* those outside of the reserved 64K legacy region.
*/
- area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END);
- if (area == NULL)
+ hose->io_base_alloc = ioremap_pbh(phys_page, size_page);
+ if (!hose->io_base_alloc)
return -ENOMEM;
- hose->io_base_alloc = area->addr;
- hose->io_base_virt = (void __iomem *)(area->addr +
- hose->io_base_phys - phys_page);
+ hose->io_base_virt = hose->io_base_alloc +
+ hose->io_base_phys - phys_page;
pr_debug("IO mapping for PHB %pOF\n", hose->dn);
pr_debug(" phys=0x%016llx, virt=0x%p (alloc=0x%p)\n",
@@ -159,11 +181,6 @@ static int pcibios_map_phb_io_space(struct pci_controller *hose)
pr_debug(" size=0x%016llx (alloc=0x%016lx)\n",
hose->pci_io_size, size_page);
- /* Establish the mapping */
- if (__ioremap_at(phys_page, area->addr, size_page,
- pgprot_noncached(PAGE_KERNEL)) == NULL)
- return -ENOMEM;
-
/* Fixup hose IO resource */
io_virt_offset = pcibios_io_space_offset(hose);
hose->io_resource.start += io_virt_offset;
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index f2741c04289d..77b229f8d218 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -178,10 +178,9 @@ static int electra_cf_probe(struct platform_device *ofdev)
struct device_node *np = ofdev->dev.of_node;
struct electra_cf_socket *cf;
struct resource mem, io;
- int status;
+ int status = -ENOMEM;
const unsigned int *prop;
int err;
- struct vm_struct *area;
err = of_address_to_resource(np, 0, &mem);
if (err)
@@ -202,30 +201,19 @@ static int electra_cf_probe(struct platform_device *ofdev)
cf->mem_phys = mem.start;
cf->mem_size = PAGE_ALIGN(resource_size(&mem));
cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
+ if (!cf->mem_base)
+ goto out_free_cf;
cf->io_size = PAGE_ALIGN(resource_size(&io));
-
- area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END);
- if (area == NULL) {
- status = -ENOMEM;
- goto fail1;
- }
-
- cf->io_virt = (void __iomem *)(area->addr);
+ cf->io_virt = ioremap_pbh(io.start, cf->io_size);
+ if (!cf->io_virt)
+ goto out_unmap_mem;
cf->gpio_base = ioremap(0xfc103000, 0x1000);
+ if (!cf->gpio_base)
+ goto out_unmap_virt;
dev_set_drvdata(device, cf);
- if (!cf->mem_base || !cf->io_virt || !cf->gpio_base ||
- (__ioremap_at(io.start, cf->io_virt, cf->io_size,
- pgprot_noncached(PAGE_KERNEL)) == NULL)) {
- dev_err(device, "can't ioremap ranges\n");
- status = -ENOMEM;
- goto fail1;
- }
-
-
cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END;
-
cf->iomem.start = (unsigned long)cf->mem_base;
cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start);
cf->iomem.flags = IORESOURCE_MEM;
@@ -305,14 +293,13 @@ static int electra_cf_probe(struct platform_device *ofdev)
if (cf->irq)
free_irq(cf->irq, cf);
- if (cf->io_virt)
- __iounmap_at(cf->io_virt, cf->io_size);
- if (cf->mem_base)
- iounmap(cf->mem_base);
- if (cf->gpio_base)
- iounmap(cf->gpio_base);
- if (area)
- device_init_wakeup(&ofdev->dev, 0);
+ iounmap(cf->gpio_base);
+out_unmap_virt:
+ device_init_wakeup(&ofdev->dev, 0);
+ iounmap(cf->io_virt);
+out_unmap_mem:
+ iounmap(cf->mem_base);
+out_free_cf:
kfree(cf);
return status;
@@ -330,7 +317,7 @@ static int electra_cf_remove(struct platform_device *ofdev)
free_irq(cf->irq, cf);
del_timer_sync(&cf->timer);
- __iounmap_at(cf->io_virt, cf->io_size);
+ iounmap(cf->io_virt);
iounmap(cf->mem_base);
iounmap(cf->gpio_base);
release_mem_region(cf->mem_phys, cf->mem_size);
--
2.25.1
^ permalink raw reply related
* [PATCH 07/28] mm: remove __get_vm_area
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
Switch the two remaining callers to use __get_vm_area_caller instead.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/powerpc/kernel/pci_64.c | 3 ++-
arch/sh/kernel/cpu/sh4/sq.c | 3 ++-
include/linux/vmalloc.h | 2 --
mm/vmalloc.c | 8 --------
4 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 8e86bd9c1eca..155e2ef60053 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -132,7 +132,8 @@ void __iomem *ioremap_pbh(phys_addr_t paddr, unsigned long size)
* address decoding but I'd rather not deal with those outside of the
* reserved 64K legacy region.
*/
- area = __get_vm_area(size, 0, PHB_IO_BASE, PHB_IO_END);
+ area = __get_vm_area_caller(size, 0, PHB_IO_BASE, PHB_IO_END,
+ __builtin_return_address(0));
if (!area)
return NULL;
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 934ff84844fa..d432164b23b7 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -103,7 +103,8 @@ static int __sq_remap(struct sq_mapping *map, pgprot_t prot)
#if defined(CONFIG_MMU)
struct vm_struct *vma;
- vma = __get_vm_area(map->size, VM_ALLOC, map->sq_addr, SQ_ADDRMAX);
+ vma = __get_vm_area_caller(map->size, VM_ALLOC, map->sq_addr,
+ SQ_ADDRMAX, __builtin_return_address(0));
if (!vma)
return -ENOMEM;
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 0507a162ccd0..3070b4dbc2d9 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -161,8 +161,6 @@ static inline size_t get_vm_area_size(const struct vm_struct *area)
extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags);
extern struct vm_struct *get_vm_area_caller(unsigned long size,
unsigned long flags, const void *caller);
-extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
- unsigned long start, unsigned long end);
extern struct vm_struct *__get_vm_area_caller(unsigned long size,
unsigned long flags,
unsigned long start, unsigned long end,
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 399f219544f7..d1534d610b48 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2127,14 +2127,6 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
return area;
}
-struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
- unsigned long start, unsigned long end)
-{
- return __get_vm_area_node(size, 1, flags, start, end, NUMA_NO_NODE,
- GFP_KERNEL, __builtin_return_address(0));
-}
-EXPORT_SYMBOL_GPL(__get_vm_area);
-
struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end,
const void *caller)
--
2.25.1
^ permalink raw reply related
* [PATCH 08/28] mm: unexport unmap_kernel_range_noflush
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
There are no modular users of this function.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/vmalloc.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index d1534d610b48..3375f9508ef6 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2029,7 +2029,6 @@ void unmap_kernel_range_noflush(unsigned long addr, unsigned long size)
{
vunmap_page_range(addr, addr + size);
}
-EXPORT_SYMBOL_GPL(unmap_kernel_range_noflush);
/**
* unmap_kernel_range - unmap kernel VM area and flush cache and TLB
--
2.25.1
^ permalink raw reply related
* [PATCH 11/28] mm: pass addr as unsigned long to vb_free
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
Ever use of addr in vb_free casts to unsigned long first, and the caller
has an unsigned long version of the address available anyway. Just pass
that and avoid all the casts.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/vmalloc.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 9183fc0d365a..aada9e9144bd 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1664,7 +1664,7 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
return vaddr;
}
-static void vb_free(const void *addr, unsigned long size)
+static void vb_free(unsigned long addr, unsigned long size)
{
unsigned long offset;
unsigned long vb_idx;
@@ -1674,24 +1674,22 @@ static void vb_free(const void *addr, unsigned long size)
BUG_ON(offset_in_page(size));
BUG_ON(size > PAGE_SIZE*VMAP_MAX_ALLOC);
- flush_cache_vunmap((unsigned long)addr, (unsigned long)addr + size);
+ flush_cache_vunmap(addr, addr + size);
order = get_order(size);
- offset = (unsigned long)addr & (VMAP_BLOCK_SIZE - 1);
- offset >>= PAGE_SHIFT;
+ offset = (addr & (VMAP_BLOCK_SIZE - 1)) >> PAGE_SHIFT;
- vb_idx = addr_to_vb_idx((unsigned long)addr);
+ vb_idx = addr_to_vb_idx(addr);
rcu_read_lock();
vb = radix_tree_lookup(&vmap_block_tree, vb_idx);
rcu_read_unlock();
BUG_ON(!vb);
- vunmap_page_range((unsigned long)addr, (unsigned long)addr + size);
+ vunmap_page_range(addr, addr + size);
if (debug_pagealloc_enabled_static())
- flush_tlb_kernel_range((unsigned long)addr,
- (unsigned long)addr + size);
+ flush_tlb_kernel_range(addr, addr + size);
spin_lock(&vb->lock);
@@ -1791,7 +1789,7 @@ void vm_unmap_ram(const void *mem, unsigned int count)
if (likely(count <= VMAP_MAX_ALLOC)) {
debug_check_no_locks_freed(mem, size);
- vb_free(mem, size);
+ vb_free(addr, size);
return;
}
--
2.25.1
^ permalink raw reply related
* [PATCH 09/28] mm: rename CONFIG_PGTABLE_MAPPING to CONFIG_ZSMALLOC_PGTABLE_MAPPING
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
Rename the Kconfig variable to clarify the scope.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
arch/arm/configs/omap2plus_defconfig | 2 +-
include/linux/zsmalloc.h | 2 +-
mm/Kconfig | 2 +-
mm/zsmalloc.c | 8 ++++----
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 3cc3ca5fa027..583d8abd80a4 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -81,7 +81,7 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BINFMT_MISC=y
CONFIG_CMA=y
CONFIG_ZSMALLOC=m
-CONFIG_PGTABLE_MAPPING=y
+CONFIG_ZSMALLOC_PGTABLE_MAPPING=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
diff --git a/include/linux/zsmalloc.h b/include/linux/zsmalloc.h
index 2219cce81ca4..0fdbf653b173 100644
--- a/include/linux/zsmalloc.h
+++ b/include/linux/zsmalloc.h
@@ -20,7 +20,7 @@
* zsmalloc mapping modes
*
* NOTE: These only make a difference when a mapped object spans pages.
- * They also have no effect when PGTABLE_MAPPING is selected.
+ * They also have no effect when ZSMALLOC_PGTABLE_MAPPING is selected.
*/
enum zs_mapmode {
ZS_MM_RW, /* normal read-write mapping */
diff --git a/mm/Kconfig b/mm/Kconfig
index 691021492e78..36949a9425b8 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -700,7 +700,7 @@ config ZSMALLOC
returned by an alloc(). This handle must be mapped in order to
access the allocated space.
-config PGTABLE_MAPPING
+config ZSMALLOC_PGTABLE_MAPPING
bool "Use page table mapping to access object in zsmalloc"
depends on ZSMALLOC
help
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 2f836a2b993f..ac0524330b9b 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -293,7 +293,7 @@ struct zspage {
};
struct mapping_area {
-#ifdef CONFIG_PGTABLE_MAPPING
+#ifdef CONFIG_ZSMALLOC_PGTABLE_MAPPING
struct vm_struct *vm; /* vm area for mapping object that span pages */
#else
char *vm_buf; /* copy buffer for objects that span pages */
@@ -1113,7 +1113,7 @@ static struct zspage *find_get_zspage(struct size_class *class)
return zspage;
}
-#ifdef CONFIG_PGTABLE_MAPPING
+#ifdef CONFIG_ZSMALLOC_PGTABLE_MAPPING
static inline int __zs_cpu_up(struct mapping_area *area)
{
/*
@@ -1151,7 +1151,7 @@ static inline void __zs_unmap_object(struct mapping_area *area,
unmap_kernel_range(addr, PAGE_SIZE * 2);
}
-#else /* CONFIG_PGTABLE_MAPPING */
+#else /* CONFIG_ZSMALLOC_PGTABLE_MAPPING */
static inline int __zs_cpu_up(struct mapping_area *area)
{
@@ -1233,7 +1233,7 @@ static void __zs_unmap_object(struct mapping_area *area,
pagefault_enable();
}
-#endif /* CONFIG_PGTABLE_MAPPING */
+#endif /* CONFIG_ZSMALLOC_PGTABLE_MAPPING */
static int zs_cpu_prepare(unsigned int cpu)
{
--
2.25.1
^ permalink raw reply related
* [PATCH 12/28] mm: remove vmap_page_range_noflush and vunmap_page_range
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
These have non-static aliases claled map_kernel_range_noflush and
unmap_kernel_range_noflush that just differ slightly in the calling
conventions that pass addr + size instead of an end.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/vmalloc.c | 98 +++++++++++++++++++++-------------------------------
1 file changed, 40 insertions(+), 58 deletions(-)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index aada9e9144bd..55df5dc6a9fc 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -127,10 +127,24 @@ static void vunmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end)
} while (p4d++, addr = next, addr != end);
}
-static void vunmap_page_range(unsigned long addr, unsigned long end)
+/**
+ * unmap_kernel_range_noflush - unmap kernel VM area
+ * @addr: start of the VM area to unmap
+ * @size: size of the VM area to unmap
+ *
+ * Unmap PFN_UP(@size) pages at @addr. The VM area @addr and @size specify
+ * should have been allocated using get_vm_area() and its friends.
+ *
+ * NOTE:
+ * This function does NOT do any cache flushing. The caller is responsible
+ * for calling flush_cache_vunmap() on to-be-mapped areas before calling this
+ * function and flush_tlb_kernel_range() after.
+ */
+void unmap_kernel_range_noflush(unsigned long addr, unsigned long size)
{
- pgd_t *pgd;
+ unsigned long end = addr + size;
unsigned long next;
+ pgd_t *pgd;
BUG_ON(addr >= end);
pgd = pgd_offset_k(addr);
@@ -219,18 +233,30 @@ static int vmap_p4d_range(pgd_t *pgd, unsigned long addr,
return 0;
}
-/*
- * Set up page tables in kva (addr, end). The ptes shall have prot "prot", and
- * will have pfns corresponding to the "pages" array.
+/**
+ * map_kernel_range_noflush - map kernel VM area with the specified pages
+ * @addr: start of the VM area to map
+ * @size: size of the VM area to map
+ * @prot: page protection flags to use
+ * @pages: pages to map
*
- * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N]
+ * Map PFN_UP(@size) pages at @addr. The VM area @addr and @size specify should
+ * have been allocated using get_vm_area() and its friends.
+ *
+ * NOTE:
+ * This function does NOT do any cache flushing. The caller is responsible for
+ * calling flush_cache_vmap() on to-be-mapped areas before calling this
+ * function.
+ *
+ * RETURNS:
+ * The number of pages mapped on success, -errno on failure.
*/
-static int vmap_page_range_noflush(unsigned long start, unsigned long end,
- pgprot_t prot, struct page **pages)
+int map_kernel_range_noflush(unsigned long addr, unsigned long size,
+ pgprot_t prot, struct page **pages)
{
- pgd_t *pgd;
+ unsigned long end = addr + size;
unsigned long next;
- unsigned long addr = start;
+ pgd_t *pgd;
int err = 0;
int nr = 0;
@@ -251,7 +277,7 @@ static int vmap_page_range(unsigned long start, unsigned long end,
{
int ret;
- ret = vmap_page_range_noflush(start, end, prot, pages);
+ ret = map_kernel_range_noflush(start, end - start, prot, pages);
flush_cache_vmap(start, end);
return ret;
}
@@ -1226,7 +1252,7 @@ EXPORT_SYMBOL_GPL(unregister_vmap_purge_notifier);
*/
static void unmap_vmap_area(struct vmap_area *va)
{
- vunmap_page_range(va->va_start, va->va_end);
+ unmap_kernel_range_noflush(va->va_start, va->va_end - va->va_start);
}
/*
@@ -1686,7 +1712,7 @@ static void vb_free(unsigned long addr, unsigned long size)
rcu_read_unlock();
BUG_ON(!vb);
- vunmap_page_range(addr, addr + size);
+ unmap_kernel_range_noflush(addr, size);
if (debug_pagealloc_enabled_static())
flush_tlb_kernel_range(addr, addr + size);
@@ -1984,50 +2010,6 @@ void __init vmalloc_init(void)
vmap_initialized = true;
}
-/**
- * map_kernel_range_noflush - map kernel VM area with the specified pages
- * @addr: start of the VM area to map
- * @size: size of the VM area to map
- * @prot: page protection flags to use
- * @pages: pages to map
- *
- * Map PFN_UP(@size) pages at @addr. The VM area @addr and @size
- * specify should have been allocated using get_vm_area() and its
- * friends.
- *
- * NOTE:
- * This function does NOT do any cache flushing. The caller is
- * responsible for calling flush_cache_vmap() on to-be-mapped areas
- * before calling this function.
- *
- * RETURNS:
- * The number of pages mapped on success, -errno on failure.
- */
-int map_kernel_range_noflush(unsigned long addr, unsigned long size,
- pgprot_t prot, struct page **pages)
-{
- return vmap_page_range_noflush(addr, addr + size, prot, pages);
-}
-
-/**
- * unmap_kernel_range_noflush - unmap kernel VM area
- * @addr: start of the VM area to unmap
- * @size: size of the VM area to unmap
- *
- * Unmap PFN_UP(@size) pages at @addr. The VM area @addr and @size
- * specify should have been allocated using get_vm_area() and its
- * friends.
- *
- * NOTE:
- * This function does NOT do any cache flushing. The caller is
- * responsible for calling flush_cache_vunmap() on to-be-mapped areas
- * before calling this function and flush_tlb_kernel_range() after.
- */
-void unmap_kernel_range_noflush(unsigned long addr, unsigned long size)
-{
- vunmap_page_range(addr, addr + size);
-}
-
/**
* unmap_kernel_range - unmap kernel VM area and flush cache and TLB
* @addr: start of the VM area to unmap
@@ -2041,7 +2023,7 @@ void unmap_kernel_range(unsigned long addr, unsigned long size)
unsigned long end = addr + size;
flush_cache_vunmap(addr, end);
- vunmap_page_range(addr, end);
+ unmap_kernel_range_noflush(addr, size);
flush_tlb_kernel_range(addr, end);
}
--
2.25.1
^ permalink raw reply related
* [PATCH 13/28] mm: rename vmap_page_range to map_kernel_range
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
This matches the map_kernel_range_noflush API. Also change to pass
a size instead of the end, similar to the noflush version.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/vmalloc.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 55df5dc6a9fc..a3d810def567 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -272,13 +272,13 @@ int map_kernel_range_noflush(unsigned long addr, unsigned long size,
return nr;
}
-static int vmap_page_range(unsigned long start, unsigned long end,
+static int map_kernel_range(unsigned long start, unsigned long size,
pgprot_t prot, struct page **pages)
{
int ret;
- ret = map_kernel_range_noflush(start, end - start, prot, pages);
- flush_cache_vmap(start, end);
+ ret = map_kernel_range_noflush(start, size, prot, pages);
+ flush_cache_vmap(start, start + size);
return ret;
}
@@ -1866,7 +1866,7 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
kasan_unpoison_vmalloc(mem, size);
- if (vmap_page_range(addr, addr + size, prot, pages) < 0) {
+ if (map_kernel_range(addr, size, prot, pages) < 0) {
vm_unmap_ram(mem, count);
return NULL;
}
@@ -2030,10 +2030,9 @@ void unmap_kernel_range(unsigned long addr, unsigned long size)
int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page **pages)
{
unsigned long addr = (unsigned long)area->addr;
- unsigned long end = addr + get_vm_area_size(area);
int err;
- err = vmap_page_range(addr, end, prot, pages);
+ err = map_kernel_range(addr, get_vm_area_size(area), prot, pages);
return err > 0 ? 0 : err;
}
--
2.25.1
^ permalink raw reply related
* [PATCH 10/28] mm: only allow page table mappings for built-in zsmalloc
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
This allows to unexport map_vm_area and unmap_kernel_range, which are
rather deep internal and should not be available to modules.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/Kconfig | 2 +-
mm/vmalloc.c | 2 --
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/mm/Kconfig b/mm/Kconfig
index 36949a9425b8..614cc786b519 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -702,7 +702,7 @@ config ZSMALLOC
config ZSMALLOC_PGTABLE_MAPPING
bool "Use page table mapping to access object in zsmalloc"
- depends on ZSMALLOC
+ depends on ZSMALLOC=y
help
By default, zsmalloc uses a copy-based object mapping method to
access allocations that span two pages. However, if a particular
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 3375f9508ef6..9183fc0d365a 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2046,7 +2046,6 @@ void unmap_kernel_range(unsigned long addr, unsigned long size)
vunmap_page_range(addr, end);
flush_tlb_kernel_range(addr, end);
}
-EXPORT_SYMBOL_GPL(unmap_kernel_range);
int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page **pages)
{
@@ -2058,7 +2057,6 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page **pages)
return err > 0 ? 0 : err;
}
-EXPORT_SYMBOL_GPL(map_vm_area);
static inline void setup_vmalloc_vm_locked(struct vm_struct *vm,
struct vmap_area *va, unsigned long flags, const void *caller)
--
2.25.1
^ permalink raw reply related
* [PATCH 14/28] mm: don't return the number of pages from map_kernel_range{, _noflush}
From: Christoph Hellwig @ 2020-04-08 11:59 UTC (permalink / raw)
To: Andrew Morton, K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger,
Wei Liu, x86, David Airlie, Daniel Vetter, Laura Abbott,
Sumit Semwal, Sakari Ailus, Minchan Kim, Nitin Gupta
Cc: linux-arch, linux-hyperv, linux-s390, Peter Zijlstra,
linuxppc-dev, linux-kernel, dri-devel, linaro-mm-sig, linux-mm,
iommu, bpf, Robin Murphy, linux-arm-kernel
In-Reply-To: <20200408115926.1467567-1-hch@lst.de>
None of the callers needs the number of pages, and a 0 / -errno return
value is a lot more intuitive.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
mm/vmalloc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index a3d810def567..ca8dc5d42580 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -249,7 +249,7 @@ static int vmap_p4d_range(pgd_t *pgd, unsigned long addr,
* function.
*
* RETURNS:
- * The number of pages mapped on success, -errno on failure.
+ * 0 on success, -errno on failure.
*/
int map_kernel_range_noflush(unsigned long addr, unsigned long size,
pgprot_t prot, struct page **pages)
@@ -269,7 +269,7 @@ int map_kernel_range_noflush(unsigned long addr, unsigned long size,
return err;
} while (pgd++, addr = next, addr != end);
- return nr;
+ return 0;
}
static int map_kernel_range(unsigned long start, unsigned long size,
--
2.25.1
^ 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