* Re: [PATCH v8 5/9] seccomp: split mode set routines
From: Kees Cook @ 2014-06-27 18:52 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Oleg Nesterov, LKML, Michael Kerrisk (man-pages),
Alexei Starovoitov, Andrew Morton, Daniel Borkmann, Will Drewry,
Julien Tinnes, David Drysdale, Linux API,
x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-mips-6z/3iImG2C8G8FEW9MqTrA, linux-arch,
linux-security-module
In-Reply-To: <CALCETrUPxTxseJ=sOhD9CyJPtOqCR5sL8yx7KezLmLZcFSFNMA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Fri, Jun 27, 2014 at 11:39 AM, Andy Lutomirski <luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org> wrote:
> On Fri, Jun 27, 2014 at 11:33 AM, Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
>> On Wed, Jun 25, 2014 at 11:07 AM, Andy Lutomirski <luto-kltTT9wpgjJwATOyAt5JVQ@public.gmane.org> wrote:
>>> On Wed, Jun 25, 2014 at 11:00 AM, Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
>>>> On Wed, Jun 25, 2014 at 10:51 AM, Oleg Nesterov <oleg-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>>>> On 06/25, Andy Lutomirski wrote:
>>>>>>
>>>>>> On Wed, Jun 25, 2014 at 10:32 AM, Oleg Nesterov <oleg-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>>>>> > On 06/25, Andy Lutomirski wrote:
>>>>>> >>
>>>>>> >> Write the filter, then smp_mb (or maybe a weaker barrier is okay),
>>>>>> >> then set the bit.
>>>>>> >
>>>>>> > Yes, exactly, this is what I meant. Plas rmb() in __secure_computing().
>>>>>> >
>>>>>> > But I still can't understand the rest of your discussion about the
>>>>>> > ordering we need ;)
>>>>>>
>>>>>> Let me try again from scratch.
>>>>>>
>>>>>> Currently there are three relevant variables: TIF_SECCOMP,
>>>>>> seccomp.mode, and seccomp.filter. __secure_computing needs
>>>>>> seccomp.mode and seccomp.filter to be in sync, and it wants (but
>>>>>> doesn't really need) TIF_SECCOMP to be in sync as well.
>>>>>>
>>>>>> My suggestion is to rearrange it a bit. Move mode into seccomp.filter
>>>>>> (so that filter == NULL implies no seccomp) and don't check
>>>>
>>>> This would require that we reimplement mode 1 seccomp via mode 2
>>>> filters. Which isn't too hard, but may add complexity.
>>>>
>>>>>> TIF_SECCOMP in secure_computing. Then turning on seccomp is entirely
>>>>>> atomic except for the fact that the seccomp hooks won't be called if
>>>>>> filter != NULL but !TIF_SECCOMP. This removes all ordering
>>>>>> requirements.
>>>>>
>>>>> Ah, got it, thanks. Perhaps I missed somehing, but to me this looks like
>>>>> unnecessary complication at first glance.
>>>>>
>>>>> We alredy have TIF_SECCOMP, we need it anyway, and we should only care
>>>>> about the case when this bit is actually set, so that we can race with
>>>>> the 1st call of __secure_computing().
>>>>>
>>>>> Otherwise we are fine: we can miss the new filter anyway, ->mode can't
>>>>> be changed it is already nonzero.
>>>>>
>>>>>> Alternatively, __secure_computing could still BUG_ON(!seccomp.filter).
>>>>>> In that case, filter needs to be set before TIF_SECCOMP is set, but
>>>>>> that's straightforward.
>>>>>
>>>>> Yep. And this is how seccomp_assign_mode() already works? It is called
>>>>> after we change ->filter chain, it changes ->mode before set(TIF_SECCOMP)
>>>>> just it lacks a barrier.
>>>>
>>>> Right, I think the best solution is to add the barrier. I was
>>>> concerned that adding the read barrier in secure_computing would have
>>>> a performance impact, though.
>>>>
>>>
>>> I can't speak for ARM, but I think that all of the read barriers are
>>> essentially free on x86. (smp_mb is a very different story, but that
>>> shouldn't be needed here.)
>>
>> It looks like SMP ARM issues dsb for rmb, which seems a bit expensive.
>> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204g/CIHJFGFE.html
>>
>> If I skip the rmb in the secure_computing call before checking mode,
>> it sounds like I run the risk of racing an out-of-order TIF_SECCOMP vs
>> mode and filter. This seems unlikely to me, given an addition of the
>> smp_mb__before_atomic() during the seccomp_assign_mode()? I guess I
>> don't have a sense of how aggressively ARM might do data caching in
>> this area. Could the other thread actually see TIF_SECCOMP get set but
>> still have an out of date copy of seccomp.mode?
>>
>> I really want to avoid adding anything to the secure_computing()
>> execution path. :(
>
> Hence my suggestion to make the ordering not matter. No ordering
> requirement, no barriers.
I may be misunderstanding something, but I think there's still an
ordering problem. We'll have TIF_SECCOMP already, so if we enter
secure_computing with a NULL filter, we'll kill the process.
Merging .mode and .filter would remove one of the race failure paths:
having TIF_SECCOMP and not having a mode set (leading to BUG). With
the merge, we could still race and land in the same place as have
TIF_SECCOMP and mode==2, but filter==NULL, leading to WARN and kill.
I guess the question is how large is the race risk on ARM? Is it
possible to have TIF_SECCOMP that far out of sync for the thread?
-Kees
--
Kees Cook
Chrome OS Security
^ permalink raw reply
* Re: [PATCH v7 2/9] seccomp: split filter prep from check and apply
From: Kees Cook @ 2014-06-27 18:45 UTC (permalink / raw)
To: David Drysdale
Cc: LKML, Andy Lutomirski, Alexei Starovoitov,
Michael Kerrisk (man-pages), Andrew Morton, Daniel Borkmann,
Oleg Nesterov, Will Drewry, Julien Tinnes, Linux API,
x86@kernel.org, linux-arm-kernel@lists.infradead.org, linux-mips,
linux-arch, linux-security-module
In-Reply-To: <20140626123710.GA16204@google.com>
On Thu, Jun 26, 2014 at 5:37 AM, David Drysdale <drysdale@google.com> wrote:
> On Mon, Jun 23, 2014 at 02:58:06PM -0700, Kees Cook wrote:
>> In preparation for adding seccomp locking, move filter creation away
>> from where it is checked and applied. This will allow for locking where
>> no memory allocation is happening. The validation, filter attachment,
>> and seccomp mode setting can all happen under the future locks.
>>
>> Signed-off-by: Kees Cook <keescook@chromium.org>
>> ---
>> kernel/seccomp.c | 97 +++++++++++++++++++++++++++++++++++++-----------------
>> 1 file changed, 67 insertions(+), 30 deletions(-)
>>
>> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
>> index afb916c7e890..edc8c79ed16d 100644
>> --- a/kernel/seccomp.c
>> +++ b/kernel/seccomp.c
>> @@ -515,6 +551,7 @@ static long seccomp_set_mode(unsigned long seccomp_mode, char __user *filter)
>> current->seccomp.mode = seccomp_mode;
>> set_thread_flag(TIF_SECCOMP);
>> out:
>> + seccomp_filter_free(prepared);
>> return ret;
>> }
>
> I think this needs to be inside #ifdef CONFIG_SECCOMP_FILTER to match
> the definition of seccomp_filter_free:
>
> ../kernel/seccomp.c:554:2: error: implicit declaration of function ‘seccomp_filter_free’ [-Werror=implicit-function-declaration]
Thanks for catching that! I've ended up rearranging the patch series
so the prepare/attach split happens after I've split the set_mode
functions now, so I've managed to avoid this condition now. :)
-Kees
--
Kees Cook
Chrome OS Security
^ permalink raw reply
* Re: [PATCH v8 5/9] seccomp: split mode set routines
From: Andy Lutomirski @ 2014-06-27 18:39 UTC (permalink / raw)
To: Kees Cook
Cc: Oleg Nesterov, LKML, Michael Kerrisk (man-pages),
Alexei Starovoitov, Andrew Morton, Daniel Borkmann, Will Drewry,
Julien Tinnes, David Drysdale, Linux API, x86@kernel.org,
linux-arm-kernel@lists.infradead.org, linux-mips, linux-arch,
linux-security-module
In-Reply-To: <CAGXu5jLavA8FJD8m-1y4wO0uzh3qvvMmajAg0Lrr1Cn_Om3a3w@mail.gmail.com>
On Fri, Jun 27, 2014 at 11:33 AM, Kees Cook <keescook@chromium.org> wrote:
> On Wed, Jun 25, 2014 at 11:07 AM, Andy Lutomirski <luto@amacapital.net> wrote:
>> On Wed, Jun 25, 2014 at 11:00 AM, Kees Cook <keescook@chromium.org> wrote:
>>> On Wed, Jun 25, 2014 at 10:51 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>>> On 06/25, Andy Lutomirski wrote:
>>>>>
>>>>> On Wed, Jun 25, 2014 at 10:32 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>>>> > On 06/25, Andy Lutomirski wrote:
>>>>> >>
>>>>> >> Write the filter, then smp_mb (or maybe a weaker barrier is okay),
>>>>> >> then set the bit.
>>>>> >
>>>>> > Yes, exactly, this is what I meant. Plas rmb() in __secure_computing().
>>>>> >
>>>>> > But I still can't understand the rest of your discussion about the
>>>>> > ordering we need ;)
>>>>>
>>>>> Let me try again from scratch.
>>>>>
>>>>> Currently there are three relevant variables: TIF_SECCOMP,
>>>>> seccomp.mode, and seccomp.filter. __secure_computing needs
>>>>> seccomp.mode and seccomp.filter to be in sync, and it wants (but
>>>>> doesn't really need) TIF_SECCOMP to be in sync as well.
>>>>>
>>>>> My suggestion is to rearrange it a bit. Move mode into seccomp.filter
>>>>> (so that filter == NULL implies no seccomp) and don't check
>>>
>>> This would require that we reimplement mode 1 seccomp via mode 2
>>> filters. Which isn't too hard, but may add complexity.
>>>
>>>>> TIF_SECCOMP in secure_computing. Then turning on seccomp is entirely
>>>>> atomic except for the fact that the seccomp hooks won't be called if
>>>>> filter != NULL but !TIF_SECCOMP. This removes all ordering
>>>>> requirements.
>>>>
>>>> Ah, got it, thanks. Perhaps I missed somehing, but to me this looks like
>>>> unnecessary complication at first glance.
>>>>
>>>> We alredy have TIF_SECCOMP, we need it anyway, and we should only care
>>>> about the case when this bit is actually set, so that we can race with
>>>> the 1st call of __secure_computing().
>>>>
>>>> Otherwise we are fine: we can miss the new filter anyway, ->mode can't
>>>> be changed it is already nonzero.
>>>>
>>>>> Alternatively, __secure_computing could still BUG_ON(!seccomp.filter).
>>>>> In that case, filter needs to be set before TIF_SECCOMP is set, but
>>>>> that's straightforward.
>>>>
>>>> Yep. And this is how seccomp_assign_mode() already works? It is called
>>>> after we change ->filter chain, it changes ->mode before set(TIF_SECCOMP)
>>>> just it lacks a barrier.
>>>
>>> Right, I think the best solution is to add the barrier. I was
>>> concerned that adding the read barrier in secure_computing would have
>>> a performance impact, though.
>>>
>>
>> I can't speak for ARM, but I think that all of the read barriers are
>> essentially free on x86. (smp_mb is a very different story, but that
>> shouldn't be needed here.)
>
> It looks like SMP ARM issues dsb for rmb, which seems a bit expensive.
> http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204g/CIHJFGFE.html
>
> If I skip the rmb in the secure_computing call before checking mode,
> it sounds like I run the risk of racing an out-of-order TIF_SECCOMP vs
> mode and filter. This seems unlikely to me, given an addition of the
> smp_mb__before_atomic() during the seccomp_assign_mode()? I guess I
> don't have a sense of how aggressively ARM might do data caching in
> this area. Could the other thread actually see TIF_SECCOMP get set but
> still have an out of date copy of seccomp.mode?
>
> I really want to avoid adding anything to the secure_computing()
> execution path. :(
Hence my suggestion to make the ordering not matter. No ordering
requirement, no barriers.
--Andy
>
> -Kees
>
> --
> Kees Cook
> Chrome OS Security
--
Andy Lutomirski
AMA Capital Management, LLC
^ permalink raw reply
* Re: [PATCH v8 5/9] seccomp: split mode set routines
From: Kees Cook @ 2014-06-27 18:33 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Oleg Nesterov, LKML, Michael Kerrisk (man-pages),
Alexei Starovoitov, Andrew Morton, Daniel Borkmann, Will Drewry,
Julien Tinnes, David Drysdale, Linux API, x86@kernel.org,
linux-arm-kernel@lists.infradead.org, linux-mips, linux-arch,
linux-security-module
In-Reply-To: <CALCETrVNwhWSPNiBiZmgP1nD9zLJPTk6cH0yo=85rbxTPTYFRg@mail.gmail.com>
On Wed, Jun 25, 2014 at 11:07 AM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Wed, Jun 25, 2014 at 11:00 AM, Kees Cook <keescook@chromium.org> wrote:
>> On Wed, Jun 25, 2014 at 10:51 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>> On 06/25, Andy Lutomirski wrote:
>>>>
>>>> On Wed, Jun 25, 2014 at 10:32 AM, Oleg Nesterov <oleg@redhat.com> wrote:
>>>> > On 06/25, Andy Lutomirski wrote:
>>>> >>
>>>> >> Write the filter, then smp_mb (or maybe a weaker barrier is okay),
>>>> >> then set the bit.
>>>> >
>>>> > Yes, exactly, this is what I meant. Plas rmb() in __secure_computing().
>>>> >
>>>> > But I still can't understand the rest of your discussion about the
>>>> > ordering we need ;)
>>>>
>>>> Let me try again from scratch.
>>>>
>>>> Currently there are three relevant variables: TIF_SECCOMP,
>>>> seccomp.mode, and seccomp.filter. __secure_computing needs
>>>> seccomp.mode and seccomp.filter to be in sync, and it wants (but
>>>> doesn't really need) TIF_SECCOMP to be in sync as well.
>>>>
>>>> My suggestion is to rearrange it a bit. Move mode into seccomp.filter
>>>> (so that filter == NULL implies no seccomp) and don't check
>>
>> This would require that we reimplement mode 1 seccomp via mode 2
>> filters. Which isn't too hard, but may add complexity.
>>
>>>> TIF_SECCOMP in secure_computing. Then turning on seccomp is entirely
>>>> atomic except for the fact that the seccomp hooks won't be called if
>>>> filter != NULL but !TIF_SECCOMP. This removes all ordering
>>>> requirements.
>>>
>>> Ah, got it, thanks. Perhaps I missed somehing, but to me this looks like
>>> unnecessary complication at first glance.
>>>
>>> We alredy have TIF_SECCOMP, we need it anyway, and we should only care
>>> about the case when this bit is actually set, so that we can race with
>>> the 1st call of __secure_computing().
>>>
>>> Otherwise we are fine: we can miss the new filter anyway, ->mode can't
>>> be changed it is already nonzero.
>>>
>>>> Alternatively, __secure_computing could still BUG_ON(!seccomp.filter).
>>>> In that case, filter needs to be set before TIF_SECCOMP is set, but
>>>> that's straightforward.
>>>
>>> Yep. And this is how seccomp_assign_mode() already works? It is called
>>> after we change ->filter chain, it changes ->mode before set(TIF_SECCOMP)
>>> just it lacks a barrier.
>>
>> Right, I think the best solution is to add the barrier. I was
>> concerned that adding the read barrier in secure_computing would have
>> a performance impact, though.
>>
>
> I can't speak for ARM, but I think that all of the read barriers are
> essentially free on x86. (smp_mb is a very different story, but that
> shouldn't be needed here.)
It looks like SMP ARM issues dsb for rmb, which seems a bit expensive.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204g/CIHJFGFE.html
If I skip the rmb in the secure_computing call before checking mode,
it sounds like I run the risk of racing an out-of-order TIF_SECCOMP vs
mode and filter. This seems unlikely to me, given an addition of the
smp_mb__before_atomic() during the seccomp_assign_mode()? I guess I
don't have a sense of how aggressively ARM might do data caching in
this area. Could the other thread actually see TIF_SECCOMP get set but
still have an out of date copy of seccomp.mode?
I really want to avoid adding anything to the secure_computing()
execution path. :(
-Kees
--
Kees Cook
Chrome OS Security
^ permalink raw reply
* Re: [PATCH v2 3/4] drm/tegra: Add SET/GET_FLAGS IOCTLs
From: Stéphane Marchesin @ 2014-06-27 18:04 UTC (permalink / raw)
To: Thierry Reding; +Cc: linux-tegra, linux-api, dri-devel@lists.freedesktop.org
In-Reply-To: <1403857706-15989-3-git-send-email-thierry.reding@gmail.com>
On Fri, Jun 27, 2014 at 1:28 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> The DRM_TEGRA_GEM_SET_FLAGS IOCTL can be used to set the flags of a
> buffer object after it has been allocated or imported. Flags associated
> with a buffer object can be queried using the DRM_TEGRA_GEM_GET_FLAGS
> IOCTL.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
> ---
> Changes in v2:
> - use -ENOENT if no GEM object is found
>
> drivers/gpu/drm/tegra/drm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++
> include/uapi/drm/tegra_drm.h | 21 +++++++++++++++++++
> 2 files changed, 70 insertions(+)
>
> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index a029525b598f..6e2e714a0649 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -548,6 +548,53 @@ static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
>
> return err;
> }
> +
> +static int tegra_gem_set_flags(struct drm_device *drm, void *data,
> + struct drm_file *file)
> +{
> + struct drm_tegra_gem_set_flags *args = data;
> + struct drm_gem_object *gem;
> + struct tegra_bo *bo;
> +
> + if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
> + return -EINVAL;
> +
> + gem = drm_gem_object_lookup(drm, file, args->handle);
> + if (!gem)
> + return -ENOENT;
> +
> + bo = to_tegra_bo(gem);
> + bo->flags = 0;
> +
> + if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
> + bo->flags |= TEGRA_BO_BOTTOM_UP;
> +
> + drm_gem_object_unreference(gem);
> +
> + return 0;
> +}
> +
> +static int tegra_gem_get_flags(struct drm_device *drm, void *data,
> + struct drm_file *file)
> +{
> + struct drm_tegra_gem_get_flags *args = data;
> + struct drm_gem_object *gem;
> + struct tegra_bo *bo;
> +
> + gem = drm_gem_object_lookup(drm, file, args->handle);
> + if (!gem)
> + return -ENOENT;
> +
> + bo = to_tegra_bo(gem);
> + args->flags = 0;
> +
> + if (bo->flags & TEGRA_BO_BOTTOM_UP)
> + args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
> +
> + drm_gem_object_unreference(gem);
> +
> + return 0;
> +}
> #endif
>
> static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
> @@ -564,6 +611,8 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
> DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
> DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
> DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
> + DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED),
> + DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED),
> #endif
> };
>
> diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
> index 0829f75eb986..c15d781ecc0f 100644
> --- a/include/uapi/drm/tegra_drm.h
> +++ b/include/uapi/drm/tegra_drm.h
> @@ -150,6 +150,23 @@ struct drm_tegra_gem_get_tiling {
> __u32 pad;
> };
>
> +#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0)
> +#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP)
> +
> +struct drm_tegra_gem_set_flags {
> + /* input */
> + __u32 handle;
> + /* output */
> + __u32 flags;
> +};
> +
> +struct drm_tegra_gem_get_flags {
> + /* input */
> + __u32 handle;
> + /* output */
> + __u32 flags;
> +};
> +
> #define DRM_TEGRA_GEM_CREATE 0x00
> #define DRM_TEGRA_GEM_MMAP 0x01
> #define DRM_TEGRA_SYNCPT_READ 0x02
> @@ -162,6 +179,8 @@ struct drm_tegra_gem_get_tiling {
> #define DRM_TEGRA_GET_SYNCPT_BASE 0x09
> #define DRM_TEGRA_GEM_SET_TILING 0x0a
> #define DRM_TEGRA_GEM_GET_TILING 0x0b
> +#define DRM_TEGRA_GEM_SET_FLAGS 0x0c
> +#define DRM_TEGRA_GEM_GET_FLAGS 0x0d
>
> #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
> #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
> @@ -175,5 +194,7 @@ struct drm_tegra_gem_get_tiling {
> #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
> #define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
> #define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
> +#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
> +#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
>
> #endif
> --
> 2.0.0
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v2 2/4] drm/tegra: Add SET/GET_TILING IOCTLs
From: Stéphane Marchesin @ 2014-06-27 17:59 UTC (permalink / raw)
To: Thierry Reding; +Cc: linux-tegra, linux-api, dri-devel@lists.freedesktop.org
In-Reply-To: <1403857706-15989-2-git-send-email-thierry.reding@gmail.com>
On Fri, Jun 27, 2014 at 1:28 AM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> Currently the tiling parameters of buffer objects can only be set at
> allocation time, and only a single tiled mode is supported. This new
> DRM_TEGRA_GEM_SET_TILING IOCTL allows more modes to be set and also
> allows the tiling mode to be changed after the allocation. This will
> enable the Tegra DRM driver to import buffers from a GPU and directly
> scan them out by configuring the display controller appropriately.
>
> To complement this, the DRM_TEGRA_GEM_GET_TILING IOCTL can query the
> current tiling mode of a buffer object. This is necessary when importing
> buffers via handle (as is done in Mesa for example) so that userspace
> can determine the proper parameters for the 2D or 3D engines.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
> ---
> Changes in v2:
> - use -ENOENT if no GEM object is found
>
> drivers/gpu/drm/tegra/drm.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
> include/uapi/drm/tegra_drm.h | 25 ++++++++++++
> 2 files changed, 120 insertions(+)
>
> diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
> index fd736efd14bd..a029525b598f 100644
> --- a/drivers/gpu/drm/tegra/drm.c
> +++ b/drivers/gpu/drm/tegra/drm.c
> @@ -455,6 +455,99 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
>
> return 0;
> }
> +
> +static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
> + struct drm_file *file)
> +{
> + struct drm_tegra_gem_set_tiling *args = data;
> + enum tegra_bo_tiling_mode mode;
> + struct drm_gem_object *gem;
> + unsigned long value = 0;
> + struct tegra_bo *bo;
> +
> + switch (args->mode) {
> + case DRM_TEGRA_GEM_TILING_MODE_PITCH:
> + mode = TEGRA_BO_TILING_MODE_PITCH;
> +
> + if (args->value != 0)
> + return -EINVAL;
> +
> + break;
> +
> + case DRM_TEGRA_GEM_TILING_MODE_TILED:
> + mode = TEGRA_BO_TILING_MODE_TILED;
> +
> + if (args->value != 0)
> + return -EINVAL;
> +
> + break;
> +
> + case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
> + mode = TEGRA_BO_TILING_MODE_BLOCK;
> +
> + if (args->value > 5)
> + return -EINVAL;
> +
> + value = args->value;
> + break;
> +
> + default:
> + return -EINVAL;
> + }
> +
> + gem = drm_gem_object_lookup(drm, file, args->handle);
> + if (!gem)
> + return -ENOENT;
> +
> + bo = to_tegra_bo(gem);
> +
> + bo->tiling.mode = mode;
> + bo->tiling.value = value;
> +
> + drm_gem_object_unreference(gem);
> +
> + return 0;
> +}
> +
> +static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
> + struct drm_file *file)
> +{
> + struct drm_tegra_gem_get_tiling *args = data;
> + struct drm_gem_object *gem;
> + struct tegra_bo *bo;
> + int err = 0;
> +
> + gem = drm_gem_object_lookup(drm, file, args->handle);
> + if (!gem)
> + return -ENOENT;
> +
> + bo = to_tegra_bo(gem);
> +
> + switch (bo->tiling.mode) {
> + case TEGRA_BO_TILING_MODE_PITCH:
> + args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
> + args->value = 0;
> + break;
> +
> + case TEGRA_BO_TILING_MODE_TILED:
> + args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
> + args->value = 0;
> + break;
> +
> + case TEGRA_BO_TILING_MODE_BLOCK:
> + args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
> + args->value = bo->tiling.value;
> + break;
> +
> + default:
> + err = -EINVAL;
> + break;
> + }
> +
> + drm_gem_object_unreference(gem);
> +
> + return err;
> +}
> #endif
>
> static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
> @@ -469,6 +562,8 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
> DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
> DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
> DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
> + DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
> + DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
> #endif
> };
>
> diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
> index b75482112428..0829f75eb986 100644
> --- a/include/uapi/drm/tegra_drm.h
> +++ b/include/uapi/drm/tegra_drm.h
> @@ -129,6 +129,27 @@ struct drm_tegra_submit {
> __u32 reserved[5]; /* future expansion */
> };
>
> +#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0
> +#define DRM_TEGRA_GEM_TILING_MODE_TILED 1
> +#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2
> +
> +struct drm_tegra_gem_set_tiling {
> + /* input */
> + __u32 handle;
> + __u32 mode;
> + __u32 value;
> + __u32 pad;
> +};
> +
> +struct drm_tegra_gem_get_tiling {
> + /* input */
> + __u32 handle;
> + /* output */
> + __u32 mode;
> + __u32 value;
> + __u32 pad;
> +};
> +
> #define DRM_TEGRA_GEM_CREATE 0x00
> #define DRM_TEGRA_GEM_MMAP 0x01
> #define DRM_TEGRA_SYNCPT_READ 0x02
> @@ -139,6 +160,8 @@ struct drm_tegra_submit {
> #define DRM_TEGRA_GET_SYNCPT 0x07
> #define DRM_TEGRA_SUBMIT 0x08
> #define DRM_TEGRA_GET_SYNCPT_BASE 0x09
> +#define DRM_TEGRA_GEM_SET_TILING 0x0a
> +#define DRM_TEGRA_GEM_GET_TILING 0x0b
>
> #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
> #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
> @@ -150,5 +173,7 @@ struct drm_tegra_submit {
> #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
> #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
> #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
> +#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
> +#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
>
> #endif
> --
> 2.0.0
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v8 3/9] seccomp: introduce writer locking
From: Kees Cook @ 2014-06-27 17:27 UTC (permalink / raw)
To: Oleg Nesterov
Cc: LKML, Andy Lutomirski, Michael Kerrisk (man-pages),
Alexei Starovoitov, Andrew Morton, Daniel Borkmann, Will Drewry,
Julien Tinnes, David Drysdale, Linux API, x86@kernel.org,
linux-arm-kernel@lists.infradead.org, linux-mips, linux-arch,
linux-security-module
In-Reply-To: <20140625180705.GB18185@redhat.com>
On Wed, Jun 25, 2014 at 11:07 AM, Oleg Nesterov <oleg@redhat.com> wrote:
> On 06/24, Kees Cook wrote:
>>
>> +static void copy_seccomp(struct task_struct *p)
>> +{
>> +#ifdef CONFIG_SECCOMP
>> + /*
>> + * Must be called with sighand->lock held, which is common to
>> + * all threads in the group. Regardless, nothing special is
>> + * needed for the child since it is not yet in the tasklist.
>> + */
>> + BUG_ON(!spin_is_locked(¤t->sighand->siglock));
>> +
>> + get_seccomp_filter(current);
>> + p->seccomp = current->seccomp;
>> +
>> + if (p->seccomp.mode != SECCOMP_MODE_DISABLED)
>> + set_tsk_thread_flag(p, TIF_SECCOMP);
>> +#endif
>> +}
>
> Wait. But what about no_new_privs? We should copy it as well...
>
> Perhaps this helper should be updated a bit and moved into seccomp.c so
> that seccomp_sync_threads() could use it too.
Ah! Yes. I had been thinking it had been copied during the task_struct
duplication, but that would have been before holding sighand->lock, so
it needs explicit recopying. Thanks!
-Kees
--
Kees Cook
Chrome OS Security
^ permalink raw reply
* Re: [PATCH 08/15] kexec: New syscall kexec_file_load() declaration
From: Michael Kerrisk (man-pages) @ 2014-06-27 12:20 UTC (permalink / raw)
To: Vivek Goyal
Cc: Andy Lutomirski,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Kexec Mailing List, Eric W. Biederman, H. Peter Anvin,
Matthew Garrett, Greg Kroah-Hartman, Borislav Petkov,
dyoung-H+wXaHxf7aLQT0dZR+AlfA, WANG Chao,
bhe-H+wXaHxf7aLQT0dZR+AlfA, Andrew Morton, Linux API
In-Reply-To: <20140627115057.GC13337-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Fri, Jun 27, 2014 at 1:50 PM, Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> On Thu, Jun 26, 2014 at 02:03:17PM -0700, Andy Lutomirski wrote:
>> On Thu, Jun 26, 2014 at 1:43 PM, Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>> > On Thu, Jun 26, 2014 at 04:33:37PM -0400, Vivek Goyal wrote:
>> >> This is the new syscall kexec_file_load() declaration/interface. I have
>> >> reserved the syscall number only for x86_64 so far. Other architectures
>> >> (including i386) can reserve syscall number when they enable the support
>> >> for this new syscall.
>> >>
>> >> Signed-off-by: Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> >> CC: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> >
>> > +.BR KEXEC_FILE_NO_INITRAMFS
>> > +Loading initrd/initramfs is optional. Specify this flag if no initramfs
>> > +is being loaded. If this flag is set, kernel will ignore the value passed
>> > +in
>>
>> This seems pointless. Why not just pass -1 for initrd_fd to indicate
>> that no initrd is needed?
>
> I was not sure whether negative fd should be treated as error and system
> call should fail or it should be treated as user does not want to load
> initrd and system call succeeds.
>
> I was concerned about the cases where application does an fd = open(),
> operation fails and fd contains -1. Caller does not check fd and
> passed it to kexec system call.
>
> I thought that in such cases we should error out saying initrd fd is
> not valid. Instead of continuing and loading kernel without initrd. A
> user might be surprised.
>
> This is little defensive programming. But I am open to change it if
> the perception is that above is not a valid concern.
Your logic for using a flag rather than -1 sounds reasonable to me.
The nearest precedent I can think of offhand is mmap(), which also
takes a file descriptor argument for some use cases. However, if
MAP_ANONYMOUS is specified, no file descriptor ir required. The
treatment of the 'fd' argument in that case depends on the system. On
Linux, the fd argument is just ignored. However, many other systems
require 'fd' to be negative when MAP_ANONYMOUS is specified; one
presumes as a kind of safety check.
Cheers,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
^ permalink raw reply
* Re: [PATCH 08/15] kexec: New syscall kexec_file_load() declaration
From: Vivek Goyal @ 2014-06-27 11:50 UTC (permalink / raw)
To: Andy Lutomirski
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Michael Kerrisk-manpages,
Eric W. Biederman, H. Peter Anvin, Matthew Garrett,
Greg Kroah-Hartman, Borislav Petkov,
dyoung-H+wXaHxf7aLQT0dZR+AlfA, chaowang-H+wXaHxf7aLQT0dZR+AlfA,
bhe-H+wXaHxf7aLQT0dZR+AlfA, Andrew Morton, Linux API
In-Reply-To: <CALCETrU8mixFxpS2Bt2Q7S08zUFxZwE1zfqHw8PEetqewgR7RQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Thu, Jun 26, 2014 at 02:03:17PM -0700, Andy Lutomirski wrote:
> On Thu, Jun 26, 2014 at 1:43 PM, Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > On Thu, Jun 26, 2014 at 04:33:37PM -0400, Vivek Goyal wrote:
> >> This is the new syscall kexec_file_load() declaration/interface. I have
> >> reserved the syscall number only for x86_64 so far. Other architectures
> >> (including i386) can reserve syscall number when they enable the support
> >> for this new syscall.
> >>
> >> Signed-off-by: Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> >> CC: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> >
> > +.BR KEXEC_FILE_NO_INITRAMFS
> > +Loading initrd/initramfs is optional. Specify this flag if no initramfs
> > +is being loaded. If this flag is set, kernel will ignore the value passed
> > +in
>
> This seems pointless. Why not just pass -1 for initrd_fd to indicate
> that no initrd is needed?
I was not sure whether negative fd should be treated as error and system
call should fail or it should be treated as user does not want to load
initrd and system call succeeds.
I was concerned about the cases where application does an fd = open(),
operation fails and fd contains -1. Caller does not check fd and
passed it to kexec system call.
I thought that in such cases we should error out saying initrd fd is
not valid. Instead of continuing and loading kernel without initrd. A
user might be surprised.
This is little defensive programming. But I am open to change it if
the perception is that above is not a valid concern.
Thanks
Vivek
^ permalink raw reply
* Re: [PATCH v2 1/4] drm/tegra: Implement more tiling modes
From: Thierry Reding @ 2014-06-27 10:45 UTC (permalink / raw)
To: Alexandre Courbot
Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
Erik Faye-Lund, Stéphane Marchesin, Daniel Vetter,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <CAAVeFu+ja-PvqMyJuCPjkTu+e7jf4rgFLPsjFD3=7CmAEfjs5A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 853 bytes --]
On Fri, Jun 27, 2014 at 07:17:24PM +0900, Alexandre Courbot wrote:
> On Fri, Jun 27, 2014 at 5:28 PM, Thierry Reding
> <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> > From: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> >
> > Tegra124 supports a block-linear mode in addition to the regular pitch
> > linear and tiled modes. Add support for these by moving the internal
> > representation into a structure rather than a simple flag.
>
> Tested-by: Alexandre Courbot <acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>
> For the 4 patches. The first one has a trivial conflict on drm.h when
> applied on today's -next.
That conflict is caused by another patch I have in my tree. I can easily
resolve that when pulling this patch to my drm/tegra/for-next branch.
Thanks for testing!
Thierry
[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH v2 1/4] drm/tegra: Implement more tiling modes
From: Alexandre Courbot @ 2014-06-27 10:17 UTC (permalink / raw)
To: Thierry Reding
Cc: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
Erik Faye-Lund, Stéphane Marchesin, Daniel Vetter,
linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1403857706-15989-1-git-send-email-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Fri, Jun 27, 2014 at 5:28 PM, Thierry Reding
<thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> From: Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>
> Tegra124 supports a block-linear mode in addition to the regular pitch
> linear and tiled modes. Add support for these by moving the internal
> representation into a structure rather than a simple flag.
Tested-by: Alexandre Courbot <acourbot-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
For the 4 patches. The first one has a trivial conflict on drm.h when
applied on today's -next.
^ permalink raw reply
* [PATCH v2 4/4] drm/tegra: Allow non-authenticated processes to create buffer objects
From: Thierry Reding @ 2014-06-27 8:28 UTC (permalink / raw)
To: dri-devel; +Cc: linux-tegra, Stéphane Marchesin, linux-api
In-Reply-To: <1403857706-15989-1-git-send-email-thierry.reding@gmail.com>
From: Thierry Reding <treding@nvidia.com>
This matches what other drivers do for equivalent IOCTLs.
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- none
drivers/gpu/drm/tegra/drm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 6e2e714a0649..5cba5e736130 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -599,7 +599,7 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
#ifdef CONFIG_DRM_TEGRA_STAGING
- DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
--
2.0.0
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH v2 3/4] drm/tegra: Add SET/GET_FLAGS IOCTLs
From: Thierry Reding @ 2014-06-27 8:28 UTC (permalink / raw)
To: dri-devel; +Cc: linux-tegra, Stéphane Marchesin, linux-api
In-Reply-To: <1403857706-15989-1-git-send-email-thierry.reding@gmail.com>
From: Thierry Reding <treding@nvidia.com>
The DRM_TEGRA_GEM_SET_FLAGS IOCTL can be used to set the flags of a
buffer object after it has been allocated or imported. Flags associated
with a buffer object can be queried using the DRM_TEGRA_GEM_GET_FLAGS
IOCTL.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- use -ENOENT if no GEM object is found
drivers/gpu/drm/tegra/drm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++
include/uapi/drm/tegra_drm.h | 21 +++++++++++++++++++
2 files changed, 70 insertions(+)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index a029525b598f..6e2e714a0649 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -548,6 +548,53 @@ static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
return err;
}
+
+static int tegra_gem_set_flags(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_set_flags *args = data;
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo;
+
+ if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
+ return -EINVAL;
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+ bo->flags = 0;
+
+ if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
+ bo->flags |= TEGRA_BO_BOTTOM_UP;
+
+ drm_gem_object_unreference(gem);
+
+ return 0;
+}
+
+static int tegra_gem_get_flags(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_get_flags *args = data;
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo;
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+ args->flags = 0;
+
+ if (bo->flags & TEGRA_BO_BOTTOM_UP)
+ args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
+
+ drm_gem_object_unreference(gem);
+
+ return 0;
+}
#endif
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
@@ -564,6 +611,8 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED),
#endif
};
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
index 0829f75eb986..c15d781ecc0f 100644
--- a/include/uapi/drm/tegra_drm.h
+++ b/include/uapi/drm/tegra_drm.h
@@ -150,6 +150,23 @@ struct drm_tegra_gem_get_tiling {
__u32 pad;
};
+#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0)
+#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP)
+
+struct drm_tegra_gem_set_flags {
+ /* input */
+ __u32 handle;
+ /* output */
+ __u32 flags;
+};
+
+struct drm_tegra_gem_get_flags {
+ /* input */
+ __u32 handle;
+ /* output */
+ __u32 flags;
+};
+
#define DRM_TEGRA_GEM_CREATE 0x00
#define DRM_TEGRA_GEM_MMAP 0x01
#define DRM_TEGRA_SYNCPT_READ 0x02
@@ -162,6 +179,8 @@ struct drm_tegra_gem_get_tiling {
#define DRM_TEGRA_GET_SYNCPT_BASE 0x09
#define DRM_TEGRA_GEM_SET_TILING 0x0a
#define DRM_TEGRA_GEM_GET_TILING 0x0b
+#define DRM_TEGRA_GEM_SET_FLAGS 0x0c
+#define DRM_TEGRA_GEM_GET_FLAGS 0x0d
#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
@@ -175,5 +194,7 @@ struct drm_tegra_gem_get_tiling {
#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
+#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
+#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
#endif
--
2.0.0
^ permalink raw reply related
* [PATCH v2 2/4] drm/tegra: Add SET/GET_TILING IOCTLs
From: Thierry Reding @ 2014-06-27 8:28 UTC (permalink / raw)
To: dri-devel; +Cc: linux-tegra, Stéphane Marchesin, linux-api
In-Reply-To: <1403857706-15989-1-git-send-email-thierry.reding@gmail.com>
From: Thierry Reding <treding@nvidia.com>
Currently the tiling parameters of buffer objects can only be set at
allocation time, and only a single tiled mode is supported. This new
DRM_TEGRA_GEM_SET_TILING IOCTL allows more modes to be set and also
allows the tiling mode to be changed after the allocation. This will
enable the Tegra DRM driver to import buffers from a GPU and directly
scan them out by configuring the display controller appropriately.
To complement this, the DRM_TEGRA_GEM_GET_TILING IOCTL can query the
current tiling mode of a buffer object. This is necessary when importing
buffers via handle (as is done in Mesa for example) so that userspace
can determine the proper parameters for the 2D or 3D engines.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- use -ENOENT if no GEM object is found
drivers/gpu/drm/tegra/drm.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
include/uapi/drm/tegra_drm.h | 25 ++++++++++++
2 files changed, 120 insertions(+)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index fd736efd14bd..a029525b598f 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -455,6 +455,99 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
return 0;
}
+
+static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_set_tiling *args = data;
+ enum tegra_bo_tiling_mode mode;
+ struct drm_gem_object *gem;
+ unsigned long value = 0;
+ struct tegra_bo *bo;
+
+ switch (args->mode) {
+ case DRM_TEGRA_GEM_TILING_MODE_PITCH:
+ mode = TEGRA_BO_TILING_MODE_PITCH;
+
+ if (args->value != 0)
+ return -EINVAL;
+
+ break;
+
+ case DRM_TEGRA_GEM_TILING_MODE_TILED:
+ mode = TEGRA_BO_TILING_MODE_TILED;
+
+ if (args->value != 0)
+ return -EINVAL;
+
+ break;
+
+ case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
+ mode = TEGRA_BO_TILING_MODE_BLOCK;
+
+ if (args->value > 5)
+ return -EINVAL;
+
+ value = args->value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+
+ bo->tiling.mode = mode;
+ bo->tiling.value = value;
+
+ drm_gem_object_unreference(gem);
+
+ return 0;
+}
+
+static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
+ struct drm_file *file)
+{
+ struct drm_tegra_gem_get_tiling *args = data;
+ struct drm_gem_object *gem;
+ struct tegra_bo *bo;
+ int err = 0;
+
+ gem = drm_gem_object_lookup(drm, file, args->handle);
+ if (!gem)
+ return -ENOENT;
+
+ bo = to_tegra_bo(gem);
+
+ switch (bo->tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
+ args->value = 0;
+ break;
+
+ case TEGRA_BO_TILING_MODE_TILED:
+ args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
+ args->value = 0;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
+ args->value = bo->tiling.value;
+ break;
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ drm_gem_object_unreference(gem);
+
+ return err;
+}
#endif
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
@@ -469,6 +562,8 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
+ DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
#endif
};
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
index b75482112428..0829f75eb986 100644
--- a/include/uapi/drm/tegra_drm.h
+++ b/include/uapi/drm/tegra_drm.h
@@ -129,6 +129,27 @@ struct drm_tegra_submit {
__u32 reserved[5]; /* future expansion */
};
+#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0
+#define DRM_TEGRA_GEM_TILING_MODE_TILED 1
+#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2
+
+struct drm_tegra_gem_set_tiling {
+ /* input */
+ __u32 handle;
+ __u32 mode;
+ __u32 value;
+ __u32 pad;
+};
+
+struct drm_tegra_gem_get_tiling {
+ /* input */
+ __u32 handle;
+ /* output */
+ __u32 mode;
+ __u32 value;
+ __u32 pad;
+};
+
#define DRM_TEGRA_GEM_CREATE 0x00
#define DRM_TEGRA_GEM_MMAP 0x01
#define DRM_TEGRA_SYNCPT_READ 0x02
@@ -139,6 +160,8 @@ struct drm_tegra_submit {
#define DRM_TEGRA_GET_SYNCPT 0x07
#define DRM_TEGRA_SUBMIT 0x08
#define DRM_TEGRA_GET_SYNCPT_BASE 0x09
+#define DRM_TEGRA_GEM_SET_TILING 0x0a
+#define DRM_TEGRA_GEM_GET_TILING 0x0b
#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
@@ -150,5 +173,7 @@ struct drm_tegra_submit {
#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
+#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
+#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
#endif
--
2.0.0
^ permalink raw reply related
* [PATCH v2 1/4] drm/tegra: Implement more tiling modes
From: Thierry Reding @ 2014-06-27 8:28 UTC (permalink / raw)
To: dri-devel; +Cc: linux-tegra, Stéphane Marchesin, linux-api
From: Thierry Reding <treding@nvidia.com>
Tegra124 supports a block-linear mode in addition to the regular pitch
linear and tiled modes. Add support for these by moving the internal
representation into a structure rather than a simple flag.
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
Changes in v2:
- none
drivers/gpu/drm/tegra/dc.c | 102 +++++++++++++++++++++++++++++++++++++-------
drivers/gpu/drm/tegra/dc.h | 5 +++
drivers/gpu/drm/tegra/drm.h | 8 +++-
drivers/gpu/drm/tegra/fb.c | 9 ++--
drivers/gpu/drm/tegra/gem.c | 2 +-
drivers/gpu/drm/tegra/gem.h | 16 ++++++-
6 files changed, 118 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index ef40381f3909..afcca04f5367 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -18,6 +18,7 @@
struct tegra_dc_soc_info {
bool supports_interlacing;
bool supports_cursor;
+ bool supports_block_linear;
};
struct tegra_plane {
@@ -212,15 +213,44 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
- if (window->tiled) {
- value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
- DC_WIN_BUFFER_ADDR_MODE_TILE;
+ if (dc->soc->supports_block_linear) {
+ unsigned long height = window->tiling.value;
+
+ switch (window->tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WINBUF_SURFACE_KIND_PITCH;
+ break;
+
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WINBUF_SURFACE_KIND_TILED;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
+ DC_WINBUF_SURFACE_KIND_BLOCK;
+ break;
+ }
+
+ tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
} else {
- value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
- DC_WIN_BUFFER_ADDR_MODE_LINEAR;
- }
+ switch (window->tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+ break;
- tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+ DC_WIN_BUFFER_ADDR_MODE_TILE;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ DRM_ERROR("hardware doesn't support block linear mode\n");
+ return -EINVAL;
+ }
+
+ tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ }
value = WIN_ENABLE;
@@ -288,6 +318,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct tegra_dc *dc = to_tegra_dc(crtc);
struct tegra_dc_window window;
unsigned int i;
+ int err;
memset(&window, 0, sizeof(window));
window.src.x = src_x >> 16;
@@ -301,7 +332,10 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
window.format = tegra_dc_format(fb->pixel_format, &window.swap);
window.bits_per_pixel = fb->bits_per_pixel;
window.bottom_up = tegra_fb_is_bottom_up(fb);
- window.tiled = tegra_fb_is_tiled(fb);
+
+ err = tegra_fb_get_tiling(fb, &window.tiling);
+ if (err < 0)
+ return err;
for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
@@ -402,8 +436,14 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
{
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
unsigned int h_offset = 0, v_offset = 0;
+ struct tegra_bo_tiling tiling;
unsigned int format, swap;
unsigned long value;
+ int err;
+
+ err = tegra_fb_get_tiling(fb, &tiling);
+ if (err < 0)
+ return err;
tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
@@ -417,15 +457,44 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
- if (tegra_fb_is_tiled(fb)) {
- value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
- DC_WIN_BUFFER_ADDR_MODE_TILE;
+ if (dc->soc->supports_block_linear) {
+ unsigned long height = tiling.value;
+
+ switch (tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WINBUF_SURFACE_KIND_PITCH;
+ break;
+
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WINBUF_SURFACE_KIND_TILED;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
+ DC_WINBUF_SURFACE_KIND_BLOCK;
+ break;
+ }
+
+ tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
} else {
- value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
- DC_WIN_BUFFER_ADDR_MODE_LINEAR;
- }
+ switch (tiling.mode) {
+ case TEGRA_BO_TILING_MODE_PITCH:
+ value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
+ DC_WIN_BUFFER_ADDR_MODE_LINEAR;
+ break;
- tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ case TEGRA_BO_TILING_MODE_TILED:
+ value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
+ DC_WIN_BUFFER_ADDR_MODE_TILE;
+ break;
+
+ case TEGRA_BO_TILING_MODE_BLOCK:
+ DRM_ERROR("hardware doesn't support block linear mode\n");
+ return -EINVAL;
+ }
+
+ tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
+ }
/* make sure bottom-up buffers are properly displayed */
if (tegra_fb_is_bottom_up(fb)) {
@@ -1277,16 +1346,19 @@ static const struct host1x_client_ops dc_client_ops = {
static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
+ .supports_block_linear = false,
};
static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
.supports_interlacing = false,
.supports_cursor = false,
+ .supports_block_linear = false,
};
static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
.supports_interlacing = true,
.supports_cursor = true,
+ .supports_block_linear = true,
};
static const struct of_device_id tegra_dc_of_match[] = {
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 78c5feff95d2..705c93b00794 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -428,6 +428,11 @@
#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
#define DC_WINBUF_UFLOW_STATUS 0x80a
+#define DC_WINBUF_SURFACE_KIND 0x80b
+#define DC_WINBUF_SURFACE_KIND_PITCH (0 << 0)
+#define DC_WINBUF_SURFACE_KIND_TILED (1 << 0)
+#define DC_WINBUF_SURFACE_KIND_BLOCK (2 << 0)
+#define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
#define DC_WINBUF_AD_UFLOW_STATUS 0xbca
#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 0d30689dff01..96d754e7b3eb 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -19,6 +19,8 @@
#include <drm/drm_fb_helper.h>
#include <drm/drm_fixed.h>
+#include "gem.h"
+
struct reset_control;
struct tegra_fb {
@@ -160,7 +162,8 @@ struct tegra_dc_window {
unsigned int stride[2];
unsigned long base[3];
bool bottom_up;
- bool tiled;
+
+ struct tegra_bo_tiling tiling;
};
/* from dc.c */
@@ -279,7 +282,8 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
unsigned int index);
bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
-bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
+int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
+ struct tegra_bo_tiling *tiling);
int tegra_drm_fb_prepare(struct drm_device *drm);
int tegra_drm_fb_init(struct drm_device *drm);
void tegra_drm_fb_exit(struct drm_device *drm);
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index fc1528e0bda1..7790d43ad082 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer)
return false;
}
-bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer)
+int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
+ struct tegra_bo_tiling *tiling)
{
struct tegra_fb *fb = to_tegra_fb(framebuffer);
- if (fb->planes[0]->flags & TEGRA_BO_TILED)
- return true;
+ /* TODO: handle YUV formats? */
+ *tiling = fb->planes[0]->tiling;
- return false;
+ return 0;
}
static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index aa85b7b26f10..c1e4e8b6e5ca 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -126,7 +126,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
goto err_mmap;
if (flags & DRM_TEGRA_GEM_CREATE_TILED)
- bo->flags |= TEGRA_BO_TILED;
+ bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED;
if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP)
bo->flags |= TEGRA_BO_BOTTOM_UP;
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
index 2f3fe96c5154..43a25c853357 100644
--- a/drivers/gpu/drm/tegra/gem.h
+++ b/drivers/gpu/drm/tegra/gem.h
@@ -16,8 +16,18 @@
#include <drm/drm.h>
#include <drm/drmP.h>
-#define TEGRA_BO_TILED (1 << 0)
-#define TEGRA_BO_BOTTOM_UP (1 << 1)
+#define TEGRA_BO_BOTTOM_UP (1 << 0)
+
+enum tegra_bo_tiling_mode {
+ TEGRA_BO_TILING_MODE_PITCH,
+ TEGRA_BO_TILING_MODE_TILED,
+ TEGRA_BO_TILING_MODE_BLOCK,
+};
+
+struct tegra_bo_tiling {
+ enum tegra_bo_tiling_mode mode;
+ unsigned long value;
+};
struct tegra_bo {
struct drm_gem_object gem;
@@ -26,6 +36,8 @@ struct tegra_bo {
struct sg_table *sgt;
dma_addr_t paddr;
void *vaddr;
+
+ struct tegra_bo_tiling tiling;
};
static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
--
2.0.0
^ permalink raw reply related
* Re: [PATCH 08/15] kexec: New syscall kexec_file_load() declaration
From: Andy Lutomirski @ 2014-06-26 21:03 UTC (permalink / raw)
To: Vivek Goyal
Cc: linux-kernel@vger.kernel.org, kexec, Michael Kerrisk-manpages,
Eric W. Biederman, H. Peter Anvin, Matthew Garrett,
Greg Kroah-Hartman, Borislav Petkov, dyoung, chaowang, bhe,
Andrew Morton, Linux API
In-Reply-To: <20140626204303.GE11136@redhat.com>
On Thu, Jun 26, 2014 at 1:43 PM, Vivek Goyal <vgoyal@redhat.com> wrote:
> On Thu, Jun 26, 2014 at 04:33:37PM -0400, Vivek Goyal wrote:
>> This is the new syscall kexec_file_load() declaration/interface. I have
>> reserved the syscall number only for x86_64 so far. Other architectures
>> (including i386) can reserve syscall number when they enable the support
>> for this new syscall.
>>
>> Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
>> CC: linux-api@vger.kernel.org
>
> +.BR KEXEC_FILE_NO_INITRAMFS
> +Loading initrd/initramfs is optional. Specify this flag if no initramfs
> +is being loaded. If this flag is set, kernel will ignore the value passed
> +in
This seems pointless. Why not just pass -1 for initrd_fd to indicate
that no initrd is needed?
--Andy
^ permalink raw reply
* Re: [PATCH 08/15] kexec: New syscall kexec_file_load() declaration
From: Vivek Goyal @ 2014-06-26 20:43 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
Cc: ebiederm-aS9lmoZGLiVWk0Htik3J/w, hpa-YMNOUZJC4hwAvxtiuMwx3w,
mjg59-1xO5oi07KQx4cg9Nei1l7Q, greg-U8xfFu+wG4EAvxtiuMwx3w,
bp-Gina5bIWoIWzQB+pC5nmwQ, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
chaowang-H+wXaHxf7aLQT0dZR+AlfA, bhe-H+wXaHxf7aLQT0dZR+AlfA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1403814824-7587-9-git-send-email-vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Thu, Jun 26, 2014 at 04:33:37PM -0400, Vivek Goyal wrote:
> This is the new syscall kexec_file_load() declaration/interface. I have
> reserved the syscall number only for x86_64 so far. Other architectures
> (including i386) can reserve syscall number when they enable the support
> for this new syscall.
>
> Signed-off-by: Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> CC: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Hi Michael,
As per feedback last time, I enhanced the existing man page to include
details of this new syscall. Here is the patch.
Thanks
Vivek
Subject: kexec_file_load() syscall man page
We already have man page for kexec_load() syscall. This patch adds details
of kexec_file_load() to same man page.
Signed-off-by: Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
man2/kexec_file_load.2 | 1
man2/kexec_load.2 | 55 +++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 50 insertions(+), 6 deletions(-)
Index: man-pages/man2/kexec_file_load.2
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ man-pages/man2/kexec_file_load.2 2014-06-25 17:39:12.056441803 -0400
@@ -0,0 +1 @@
+.so man2/kexec_load.2
Index: man-pages/man2/kexec_load.2
===================================================================
--- man-pages.orig/man2/kexec_load.2 2014-06-25 17:36:09.237453355 -0400
+++ man-pages/man2/kexec_load.2 2014-06-26 11:11:49.599810213 -0400
@@ -25,17 +25,26 @@
.\"
.TH KEXEC_LOAD 2 2012-07-13 "Linux" "Linux Programmer's Manual"
.SH NAME
-kexec_load \- load a new kernel for later execution
+kexec_load, kexec_file_load \- load a new kernel for later execution
.SH SYNOPSIS
.B #include <linux/kexec.h>
.br
+
.BI "long kexec_load(unsigned long " entry ", unsigned long " nr_segments ","
.br
.BI " struct kexec_segment *" segments \
", unsigned long " flags ");"
+.br
+
+.BI "int kexec_file_load(int " kernel_fd ", int " initrd_fd ","
+.br
+.BI " unsigned long " cmdline_len \
+", const char *" cmdline ","
+.br
+.BI " unsigned long " flags ");"
.IR Note :
-There is no glibc wrapper for this system call; see NOTES.
+There are no glibc wrappers for these system calls; see NOTES.
.SH DESCRIPTION
The
.BR kexec_load ()
@@ -111,11 +120,42 @@ struct kexec_segment {
The kernel image defined by
.I segments
is copied from the calling process into previously reserved memory.
+.SS kexec_file_load()
+The
+.BR kexec_file_load ()
+system call is similar to
+.BR kexec_load(),
+but it takes a different set of arguments. It reads kernel to be loaded from
+file descriptor
+.IR kernel_fd
+and initrd to be loaded from file descriptor
+.IR initrd_fd .
+It also takes length of kernel command line in
+.IR cmdline_len
+and pointer to command line in
+.IR cmdline .
+
+The
+.IR flags
+argument is a mask which allows control over system call operation. The
+following values can be specified in
+.IR flags
+
+.TP
+.BR KEXEC_FILE_UNLOAD
+Unload currently loaded kernel.
+.TP
+.BR KEXEC_FILE_ON_CRASH
+Load kernel in memory region reserved for crash kernel. This kernel is
+booted into if currently running kernel crashes.
+.TP
+.BR KEXEC_FILE_NO_INITRAMFS
+Loading initrd/initramfs is optional. Specify this flag if no initramfs
+is being loaded. If this flag is set, kernel will ignore the value passed
+in
+.IR initrd_fd
.SH RETURN VALUE
-On success,
-.BR kexec_load ()
-returns 0.
-On error, \-1 is returned and
+On success, these system calls returns 0. On error, \-1 is returned and
.I errno
is set to indicate the error.
.SH ERRORS
@@ -135,6 +175,9 @@ is too large
The caller does not have the
.BR CAP_SYS_BOOT
capability.
+.TP
+.B ENOEXEC
+kernel_fd does not refer to an open file. Or kernel can't load this file.
.SH VERSIONS
The
.BR kexec_load ()
^ permalink raw reply
* [PATCH 08/15] kexec: New syscall kexec_file_load() declaration
From: Vivek Goyal @ 2014-06-26 20:33 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: mjg59-1xO5oi07KQx4cg9Nei1l7Q, bhe-H+wXaHxf7aLQT0dZR+AlfA,
greg-U8xfFu+wG4EAvxtiuMwx3w, Vivek Goyal,
bp-Gina5bIWoIWzQB+pC5nmwQ, ebiederm-aS9lmoZGLiVWk0Htik3J/w,
hpa-YMNOUZJC4hwAvxtiuMwx3w, akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-api-u79uwXL29TY76Z2rM5mHXA, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
chaowang-H+wXaHxf7aLQT0dZR+AlfA
In-Reply-To: <1403814824-7587-1-git-send-email-vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
This is the new syscall kexec_file_load() declaration/interface. I have
reserved the syscall number only for x86_64 so far. Other architectures
(including i386) can reserve syscall number when they enable the support
for this new syscall.
Signed-off-by: Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
CC: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
---
arch/x86/syscalls/syscall_64.tbl | 1 +
include/linux/syscalls.h | 4 ++++
kernel/kexec.c | 7 +++++++
kernel/sys_ni.c | 1 +
4 files changed, 13 insertions(+)
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index ec255a1..6d35459 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -323,6 +323,7 @@
314 common sched_setattr sys_sched_setattr
315 common sched_getattr sys_sched_getattr
316 common renameat2 sys_renameat2
+317 common kexec_file_load sys_kexec_file_load
#
# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index b0881a0..9e98193 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -317,6 +317,10 @@ asmlinkage long sys_restart_syscall(void);
asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
struct kexec_segment __user *segments,
unsigned long flags);
+asmlinkage long sys_kexec_file_load(int kernel_fd, int initrd_fd,
+ unsigned long cmdline_len,
+ const char __user *cmdline_ptr,
+ unsigned long flags);
asmlinkage long sys_exit(int error_code);
asmlinkage long sys_exit_group(int error_code);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index c69ce00..bdda717 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1057,6 +1057,13 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
}
#endif
+SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
+ unsigned long, cmdline_len, const char __user *, cmdline_ptr,
+ unsigned long, flags)
+{
+ return -ENOSYS;
+}
+
void crash_kexec(struct pt_regs *regs)
{
/* Take the kexec_mutex here to prevent sys_kexec_load
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 36441b5..51ea89f 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -25,6 +25,7 @@ cond_syscall(sys_swapon);
cond_syscall(sys_swapoff);
cond_syscall(sys_kexec_load);
cond_syscall(compat_sys_kexec_load);
+cond_syscall(sys_kexec_file_load);
cond_syscall(sys_init_module);
cond_syscall(sys_finit_module);
cond_syscall(sys_delete_module);
--
1.9.0
^ permalink raw reply related
* Re: [PATCH v2] mm: export NR_SHMEM via sysinfo(2) / si_meminfo() interfaces
From: Rik van Riel @ 2014-06-26 20:06 UTC (permalink / raw)
To: Rafael Aquini, linux-mm
Cc: Andrew Morton, Mel Gorman, Johannes Weiner, KOSAKI Motohiro,
linux-kernel, linux-api
In-Reply-To: <198dc298821a20a476656dccc85a8d77f166c61a.1403812625.git.aquini@redhat.com>
On 06/26/2014 04:00 PM, Rafael Aquini wrote:
> Historically, we exported shared pages to userspace via sysinfo(2) sharedram
> and /proc/meminfo's "MemShared" fields. With the advent of tmpfs, from kernel
> v2.4 onward, that old way for accounting shared mem was deemed inaccurate and
> we started to export a hard-coded 0 for sysinfo.sharedram. Later on, during
> the 2.6 timeframe, "MemShared" got re-introduced to /proc/meminfo re-branded
> as "Shmem", but we're still reporting sysinfo.sharedmem as that old hard-coded
> zero, which makes the "shared memory" report inconsistent across interfaces.
>
> This patch leverages the addition of explicit accounting for pages used by
> shmem/tmpfs -- "4b02108 mm: oom analysis: add shmem vmstat" -- in order to
> make the users of sysinfo(2) and si_meminfo*() friends aware of that
> vmstat entry and make them report it consistently across the interfaces,
> as well to make sysinfo(2) returned data consistent with our current API
> documentation states.
>
> Signed-off-by: Rafael Aquini <aquini@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [PATCH v2] mm: export NR_SHMEM via sysinfo(2) / si_meminfo() interfaces
From: Rafael Aquini @ 2014-06-26 20:00 UTC (permalink / raw)
To: linux-mm
Cc: Andrew Morton, Rik van Riel, Mel Gorman, Johannes Weiner,
KOSAKI Motohiro, linux-kernel, linux-api
Historically, we exported shared pages to userspace via sysinfo(2) sharedram
and /proc/meminfo's "MemShared" fields. With the advent of tmpfs, from kernel
v2.4 onward, that old way for accounting shared mem was deemed inaccurate and
we started to export a hard-coded 0 for sysinfo.sharedram. Later on, during
the 2.6 timeframe, "MemShared" got re-introduced to /proc/meminfo re-branded
as "Shmem", but we're still reporting sysinfo.sharedmem as that old hard-coded
zero, which makes the "shared memory" report inconsistent across interfaces.
This patch leverages the addition of explicit accounting for pages used by
shmem/tmpfs -- "4b02108 mm: oom analysis: add shmem vmstat" -- in order to
make the users of sysinfo(2) and si_meminfo*() friends aware of that
vmstat entry and make them report it consistently across the interfaces,
as well to make sysinfo(2) returned data consistent with our current API
documentation states.
Signed-off-by: Rafael Aquini <aquini@redhat.com>
---
Changelog from v1:
- updated commit log message to include historical context (kosaki-san)
drivers/base/node.c | 2 +-
fs/proc/meminfo.c | 2 +-
mm/page_alloc.c | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 8f7ed99..c6d3ae0 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -126,7 +126,7 @@ static ssize_t node_read_meminfo(struct device *dev,
nid, K(node_page_state(nid, NR_FILE_PAGES)),
nid, K(node_page_state(nid, NR_FILE_MAPPED)),
nid, K(node_page_state(nid, NR_ANON_PAGES)),
- nid, K(node_page_state(nid, NR_SHMEM)),
+ nid, K(i.sharedram),
nid, node_page_state(nid, NR_KERNEL_STACK) *
THREAD_SIZE / 1024,
nid, K(node_page_state(nid, NR_PAGETABLE)),
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 7445af0..aa1eee0 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -168,7 +168,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
K(global_page_state(NR_WRITEBACK)),
K(global_page_state(NR_ANON_PAGES)),
K(global_page_state(NR_FILE_MAPPED)),
- K(global_page_state(NR_SHMEM)),
+ K(i.sharedram),
K(global_page_state(NR_SLAB_RECLAIMABLE) +
global_page_state(NR_SLAB_UNRECLAIMABLE)),
K(global_page_state(NR_SLAB_RECLAIMABLE)),
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 20d17f8..f72ea38 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3040,7 +3040,7 @@ static inline void show_node(struct zone *zone)
void si_meminfo(struct sysinfo *val)
{
val->totalram = totalram_pages;
- val->sharedram = 0;
+ val->sharedram = global_page_state(NR_SHMEM);
val->freeram = global_page_state(NR_FREE_PAGES);
val->bufferram = nr_blockdev_pages();
val->totalhigh = totalhigh_pages;
@@ -3060,6 +3060,7 @@ void si_meminfo_node(struct sysinfo *val, int nid)
for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++)
managed_pages += pgdat->node_zones[zone_type].managed_pages;
val->totalram = managed_pages;
+ val->sharedram = node_page_state(nid, NR_SHMEM);
val->freeram = node_page_state(nid, NR_FREE_PAGES);
#ifdef CONFIG_HIGHMEM
val->totalhigh = pgdat->node_zones[ZONE_HIGHMEM].managed_pages;
--
1.9.3
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* Re: [PATCH v7 2/9] seccomp: split filter prep from check and apply
From: David Drysdale @ 2014-06-26 12:37 UTC (permalink / raw)
To: Kees Cook
Cc: linux-kernel, Andy Lutomirski, Alexei Starovoitov,
Michael Kerrisk (man-pages), Andrew Morton, Daniel Borkmann,
Oleg Nesterov, Will Drewry, Julien Tinnes, linux-api, x86,
linux-arm-kernel, linux-mips, linux-arch, linux-security-module
In-Reply-To: <1403560693-21809-3-git-send-email-keescook@chromium.org>
On Mon, Jun 23, 2014 at 02:58:06PM -0700, Kees Cook wrote:
> In preparation for adding seccomp locking, move filter creation away
> from where it is checked and applied. This will allow for locking where
> no memory allocation is happening. The validation, filter attachment,
> and seccomp mode setting can all happen under the future locks.
>
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
> kernel/seccomp.c | 97 +++++++++++++++++++++++++++++++++++++-----------------
> 1 file changed, 67 insertions(+), 30 deletions(-)
>
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index afb916c7e890..edc8c79ed16d 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -515,6 +551,7 @@ static long seccomp_set_mode(unsigned long seccomp_mode, char __user *filter)
> current->seccomp.mode = seccomp_mode;
> set_thread_flag(TIF_SECCOMP);
> out:
> + seccomp_filter_free(prepared);
> return ret;
> }
I think this needs to be inside #ifdef CONFIG_SECCOMP_FILTER to match
the definition of seccomp_filter_free:
../kernel/seccomp.c:554:2: error: implicit declaration of function ‘seccomp_filter_free’ [-Werror=implicit-function-declaration]
^ permalink raw reply
* Re: [PATCH v3 0/2] block: virtio-blk: support multi vq per virtio-blk
From: Ming Lei @ 2014-06-26 12:04 UTC (permalink / raw)
To: Jens Axboe, Linux Kernel Mailing List
Cc: Michael S. Tsirkin, linux-api, Linux Virtualization,
Stefan Hajnoczi, Paolo Bonzini
In-Reply-To: <1403775708-22244-1-git-send-email-ming.lei@canonical.com>
On Thu, Jun 26, 2014 at 5:41 PM, Ming Lei <ming.lei@canonical.com> wrote:
> Hi,
>
> These patches try to support multi virtual queues(multi-vq) in one
> virtio-blk device, and maps each virtual queue(vq) to blk-mq's
> hardware queue.
>
> With this approach, both scalability and performance on virtio-blk
> device can get improved.
>
> For verifying the improvement, I implements virtio-blk multi-vq over
> qemu's dataplane feature, and both handling host notification
> from each vq and processing host I/O are still kept in the per-device
> iothread context, the change is based on qemu v2.0.0 release, and
> can be accessed from below tree:
>
> git://kernel.ubuntu.com/ming/qemu.git #v2.0.0-virtblk-mq.1
>
> For enabling the multi-vq feature, 'num_queues=N' need to be added into
> '-device virtio-blk-pci ...' of qemu command line, and suggest to pass
> 'vectors=N+1' to keep one MSI irq vector per each vq, and the feature
> depends on x-data-plane.
>
> Fio(libaio, randread, iodepth=64, bs=4K, jobs=N) is run inside VM to
> verify the improvement.
>
> I just create a small quadcore VM and run fio inside the VM, and
> num_queues of the virtio-blk device is set as 2, but looks the
> improvement is still obvious. The host is 2 sockets, 8cores(16threads)
> server.
>
> 1), about scalability
> - jobs = 2, thoughput: +33%
> - jobs = 4, thoughput: +100%
>
> 2), about top thoughput: +39%
>
> So in my test, even for a quad-core VM, if the virtqueue number
> is increased from 1 to 2, both scalability and performance can
> get improved a lot.
>
> In above qemu implementation of virtio-blk-mq device, only one
> IOthread handles requests from all vqs, and the above throughput
> data has been very close to same fio test in host side with single
> job. So more improvement should be observed once more IOthreads are
> used for handling requests from multi vqs.
>
> TODO:
> - adjust vq's irq smp_affinity according to blk-mq hw queue's cpumask
>
> V3:
> - fix use-after-free on vq->name reported by Michael
>
> V2: (suggestions from Michael and Dave Chinner)
> - allocate virtqueues' pointers dynamically
> - make sure the per-queue spinlock isn't kept in same cache line
> - make each queue's name different
>
> V1:
> - remove RFC since no one objects
> - add '__u8 unused' for pending as suggested by Rusty
> - use virtio_cread_feature() directly, suggested by Rusty
Sorry, please add Jens' reviewed-by.
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Thanks,
--
Ming Lei
^ permalink raw reply
* RE: [PATCH v2] ns: introduce getnspid syscall
From: chenhanxiao-BthXqXjhjHXQFUHtdCDX3A @ 2014-06-26 10:19 UTC (permalink / raw)
To: Serge Hallyn
Cc: Eric W. Biederman, Richard Weinberger,
containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Oleg Nesterov, David Howells, Al Viro,
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Gotou, Yasunori, Pavel Emelyanov
In-Reply-To: <20140625143831.GB17169@ubuntumail>
> -----Original Message-----
> From: Serge Hallyn [mailto:serge.hallyn@ubuntu.com]
> Sent: Wednesday, June 25, 2014 10:39 PM
> To: Chen, Hanxiao/陈 晗霄
> Cc: Serge E. Hallyn; Eric W. Biederman; Richard Weinberger;
> containers@lists.linux-foundation.org; linux-kernel@vger.kernel.org; Oleg
> Nesterov; David Howells; Al Viro; linux-api@vger.kernel.org
> > > > > >
> > > > >
> > > > > I don't think that adding a new system call for this is a good solution.
> > > > > We need a more generic way. I bet people are interested in more than just
> > > PID
> > > > > numbers.
> > > >
> > > > Could you please give some hints on how to expand this interface?
> > > >
> > > > >
> > > > > I agree with Eric that a procfs solution is more appropriate.
> > > > >
> > > >
> > > > Procfs is a good solution, but syscall is not bad though.
> > >
> > > I might be inclined to agree, except that in this case you are still
> > > needing mounted procfs anyway to get the proc/$pid/ns/pid fds.
> > >
> > > I'm sorry, I've not been watching this thread, so this probably has been
> > > considered and decided against, but I'm going to ask anyway. Keeping
> > > in mind both checkpoint-restart and and introspection for use in a
> > > setns'd commend, why not make it
> > >
> > > pid_t getnspid(pid_t query_pid, pid_t observer_pid)
> > >
> > > which returns the process id of query_pid as seen from observer_pid's
> > > pidns?
> > >
> >
> > But this could be confused in nested ns.
> >
> > Ex:
> > (thanks for Pavel's figure)
> > init_pid_ns ns1 ns2
> > t1 2
> > t2 `- 3 1
> > t3 `- 4 `- 5 1
> > t4 5
> >
> > a) getnspid(1, 1):
> > We expected it could return t2's pid(2nd 1 as pid
>
> Clearly the passed-in pids should be interpreted as relative
> to current's pidns. There can be no ambiguity at that point,
> unless I'm overlooking something.
>
Default to current's pidns looks reasonable.
But nested namespace will still bring trouble to us.
Since the middle level of namespace looks less attractive to users,
how about ignore them, and just show the deepest level's pid?
Ex:
(Thanks for Pavel's figure again)
init_pid_ns ns1 ns2
t1 2
t2 `- 3 1
t3 `- 4 `- 5 1
t4 `- 5 `-7 `- 2
1. In init_pid_ns:
a) getnspid(2, 1):
returns 2 (t1)
b) getnspid(1, 3):
returns 3 (t2)
c) getnspid(1, 4):
returns 4 (t3)
getnspid(2, 4):
returns 5 (t3)
2. In ns1
a) getnspid(2, 5):
returns 7 (t4)
How do you like this idea?
Thanks,
- Chen
> > such as systemd in init_pid_ns),
> > but t3'pid is also an appropriate result.
> > We may get more than one returns.
> >
> > b) getnspid(5, 1):
> > (1st 5 was expected as pid in ns1)
> > t3'pid and t4's pid could both be the answer.
> > We could not determine which one is what we want.
> >
> > So something unique like fds of ns should be
> > a better reference.
> >
> > Thanks,
> > - Chen
> >
> > >
> > > > Procfs works for me, but that seems could not fit
> > > > Pavel's requirement.
> > > > His opinion is that a syscall is a more generic interface
> > > > than proc files, and also very helpful.
> > > > And syscall could tell whether a pid lives in a specific pid namespace,
> > > > much convenient than procfs.
> > > >
> > > > Thanks,
> > > > - Chen
> > >
> > > > _______________________________________________
> > > > Containers mailing list
> > > > Containers@lists.linux-foundation.org
> > > > https://lists.linuxfoundation.org/mailman/listinfo/containers
> >
> > _______________________________________________
> > Containers mailing list
> > Containers@lists.linux-foundation.org
> > https://lists.linuxfoundation.org/mailman/listinfo/containers
^ permalink raw reply
* [PATCH v3 2/2] block: virtio-blk: support multi virt queues per virtio-blk device
From: Ming Lei @ 2014-06-26 9:41 UTC (permalink / raw)
To: Jens Axboe, linux-kernel
Cc: Michael S. Tsirkin, linux-api, Ming Lei, virtualization,
Stefan Hajnoczi, Paolo Bonzini
In-Reply-To: <1403775708-22244-1-git-send-email-ming.lei@canonical.com>
Firstly this patch supports more than one virtual queues for virtio-blk
device.
Secondly this patch maps the virtual queue to blk-mq's hardware queue.
With this approach, both scalability and performance can be improved.
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
drivers/block/virtio_blk.c | 104 +++++++++++++++++++++++++++++++++++---------
1 file changed, 84 insertions(+), 20 deletions(-)
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index f63d358..0a58140 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -15,17 +15,22 @@
#include <linux/numa.h>
#define PART_BITS 4
+#define VQ_NAME_LEN 16
static int major;
static DEFINE_IDA(vd_index_ida);
static struct workqueue_struct *virtblk_wq;
+struct virtio_blk_vq {
+ struct virtqueue *vq;
+ spinlock_t lock;
+ char name[VQ_NAME_LEN];
+} ____cacheline_aligned_in_smp;
+
struct virtio_blk
{
struct virtio_device *vdev;
- struct virtqueue *vq;
- spinlock_t vq_lock;
/* The disk structure for the kernel. */
struct gendisk *disk;
@@ -47,6 +52,10 @@ struct virtio_blk
/* Ida index - used to track minor number allocations. */
int index;
+
+ /* num of vqs */
+ int num_vqs;
+ struct virtio_blk_vq *vqs;
};
struct virtblk_req
@@ -133,14 +142,15 @@ static void virtblk_done(struct virtqueue *vq)
{
struct virtio_blk *vblk = vq->vdev->priv;
bool req_done = false;
+ int qid = vq->index;
struct virtblk_req *vbr;
unsigned long flags;
unsigned int len;
- spin_lock_irqsave(&vblk->vq_lock, flags);
+ spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
do {
virtqueue_disable_cb(vq);
- while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
+ while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
blk_mq_complete_request(vbr->req);
req_done = true;
}
@@ -151,7 +161,7 @@ static void virtblk_done(struct virtqueue *vq)
/* In case queue is stopped waiting for more buffers. */
if (req_done)
blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
- spin_unlock_irqrestore(&vblk->vq_lock, flags);
+ spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
}
static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
@@ -160,6 +170,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
unsigned long flags;
unsigned int num;
+ int qid = hctx->queue_num;
const bool last = (req->cmd_flags & REQ_END) != 0;
int err;
bool notify = false;
@@ -202,12 +213,12 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
}
- spin_lock_irqsave(&vblk->vq_lock, flags);
- err = __virtblk_add_req(vblk->vq, vbr, vbr->sg, num);
+ spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
+ err = __virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
if (err) {
- virtqueue_kick(vblk->vq);
+ virtqueue_kick(vblk->vqs[qid].vq);
blk_mq_stop_hw_queue(hctx);
- spin_unlock_irqrestore(&vblk->vq_lock, flags);
+ spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
/* Out of mem doesn't actually happen, since we fall back
* to direct descriptors */
if (err == -ENOMEM || err == -ENOSPC)
@@ -215,12 +226,12 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req)
return BLK_MQ_RQ_QUEUE_ERROR;
}
- if (last && virtqueue_kick_prepare(vblk->vq))
+ if (last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
notify = true;
- spin_unlock_irqrestore(&vblk->vq_lock, flags);
+ spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
if (notify)
- virtqueue_notify(vblk->vq);
+ virtqueue_notify(vblk->vqs[qid].vq);
return BLK_MQ_RQ_QUEUE_OK;
}
@@ -377,12 +388,64 @@ static void virtblk_config_changed(struct virtio_device *vdev)
static int init_vq(struct virtio_blk *vblk)
{
int err = 0;
+ int i;
+ vq_callback_t **callbacks;
+ const char **names;
+ struct virtqueue **vqs;
+ unsigned short num_vqs;
+ struct virtio_device *vdev = vblk->vdev;
+
+ err = virtio_cread_feature(vdev, VIRTIO_BLK_F_MQ,
+ struct virtio_blk_config, num_queues,
+ &num_vqs);
+ if (err)
+ num_vqs = 1;
+
+ vblk->vqs = kmalloc(sizeof(*vblk->vqs) * num_vqs, GFP_KERNEL);
+ if (!vblk->vqs) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ names = kmalloc(sizeof(*names) * num_vqs, GFP_KERNEL);
+ if (!names)
+ goto err_names;
+
+ callbacks = kmalloc(sizeof(*callbacks) * num_vqs, GFP_KERNEL);
+ if (!callbacks)
+ goto err_callbacks;
+
+ vqs = kmalloc(sizeof(*vqs) * num_vqs, GFP_KERNEL);
+ if (!vqs)
+ goto err_vqs;
- /* We expect one virtqueue, for output. */
- vblk->vq = virtio_find_single_vq(vblk->vdev, virtblk_done, "requests");
- if (IS_ERR(vblk->vq))
- err = PTR_ERR(vblk->vq);
+ for (i = 0; i < num_vqs; i++) {
+ callbacks[i] = virtblk_done;
+ snprintf(vblk->vqs[i].name, VQ_NAME_LEN, "req.%d", i);
+ names[i] = vblk->vqs[i].name;
+ }
+
+ /* Discover virtqueues and write information to configuration. */
+ err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names);
+ if (err)
+ goto err_find_vqs;
+ for (i = 0; i < num_vqs; i++) {
+ spin_lock_init(&vblk->vqs[i].lock);
+ vblk->vqs[i].vq = vqs[i];
+ }
+ vblk->num_vqs = num_vqs;
+
+ err_find_vqs:
+ kfree(vqs);
+ err_vqs:
+ kfree(callbacks);
+ err_callbacks:
+ kfree(names);
+ err_names:
+ if (err)
+ kfree(vblk->vqs);
+ out:
return err;
}
@@ -551,7 +614,6 @@ static int virtblk_probe(struct virtio_device *vdev)
err = init_vq(vblk);
if (err)
goto out_free_vblk;
- spin_lock_init(&vblk->vq_lock);
/* FIXME: How many partitions? How long is a piece of string? */
vblk->disk = alloc_disk(1 << PART_BITS);
@@ -562,7 +624,7 @@ static int virtblk_probe(struct virtio_device *vdev)
/* Default queue sizing is to fill the ring. */
if (!virtblk_queue_depth) {
- virtblk_queue_depth = vblk->vq->num_free;
+ virtblk_queue_depth = vblk->vqs[0].vq->num_free;
/* ... but without indirect descs, we use 2 descs per req */
if (!virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC))
virtblk_queue_depth /= 2;
@@ -570,7 +632,6 @@ static int virtblk_probe(struct virtio_device *vdev)
memset(&vblk->tag_set, 0, sizeof(vblk->tag_set));
vblk->tag_set.ops = &virtio_mq_ops;
- vblk->tag_set.nr_hw_queues = 1;
vblk->tag_set.queue_depth = virtblk_queue_depth;
vblk->tag_set.numa_node = NUMA_NO_NODE;
vblk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
@@ -578,6 +639,7 @@ static int virtblk_probe(struct virtio_device *vdev)
sizeof(struct virtblk_req) +
sizeof(struct scatterlist) * sg_elems;
vblk->tag_set.driver_data = vblk;
+ vblk->tag_set.nr_hw_queues = vblk->num_vqs;
err = blk_mq_alloc_tag_set(&vblk->tag_set);
if (err)
@@ -727,6 +789,7 @@ static void virtblk_remove(struct virtio_device *vdev)
refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
put_disk(vblk->disk);
vdev->config->del_vqs(vdev);
+ kfree(vblk->vqs);
kfree(vblk);
/* Only free device id if we don't have any users */
@@ -777,7 +840,8 @@ static const struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
- VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
+ VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
+ VIRTIO_BLK_F_MQ,
};
static struct virtio_driver virtio_blk = {
--
1.7.9.5
^ permalink raw reply related
* [PATCH v3 1/2] include/uapi/linux/virtio_blk.h: introduce feature of VIRTIO_BLK_F_MQ
From: Ming Lei @ 2014-06-26 9:41 UTC (permalink / raw)
To: Jens Axboe, linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Rusty Russell, linux-api-u79uwXL29TY76Z2rM5mHXA,
virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
Michael S. Tsirkin, Stefan Hajnoczi, Paolo Bonzini, Ming Lei
In-Reply-To: <1403775708-22244-1-git-send-email-ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Current virtio-blk spec only supports one virtual queue for transfering
data between VM and host, and inside VM all kinds of operations on
the virtual queue needs to hold one lock, so cause below problems:
- bad scalability
- bad throughput
This patch requests to introduce feature of VIRTIO_BLK_F_MQ
so that more than one virtual queues can be used to virtio-blk
device, then above problems can be solved or eased.
Signed-off-by: Ming Lei <ming.lei-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
include/uapi/linux/virtio_blk.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/uapi/linux/virtio_blk.h b/include/uapi/linux/virtio_blk.h
index 6d8e61c..9ad67b2 100644
--- a/include/uapi/linux/virtio_blk.h
+++ b/include/uapi/linux/virtio_blk.h
@@ -40,6 +40,7 @@
#define VIRTIO_BLK_F_WCE 9 /* Writeback mode enabled after reset */
#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
+#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */
#ifndef __KERNEL__
/* Old (deprecated) name for VIRTIO_BLK_F_WCE. */
@@ -77,6 +78,10 @@ struct virtio_blk_config {
/* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
__u8 wce;
+ __u8 unused;
+
+ /* number of vqs, only available when VIRTIO_BLK_F_MQ is set */
+ __u16 num_queues;
} __attribute__((packed));
/*
--
1.7.9.5
^ 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