* [PATCH net V2] vhost: log dirty page correctly
From: Jason Wang @ 2019-01-09 7:29 UTC (permalink / raw)
To: mst, jasowang; +Cc: Jintack Lim, netdev, linux-kernel, kvm, virtualization
Vhost dirty page logging API is designed to sync through GPA. But we
try to log GIOVA when device IOTLB is enabled. This is wrong and may
lead to missing data after migration.
To solve this issue, when logging with device IOTLB enabled, we will:
1) reuse the device IOTLB translation result of GIOVA->HVA mapping to
get HVA, for writable descriptor, get HVA through iovec. For used
ring update, translate its GIOVA to HVA
2) traverse the GPA->HVA mapping to get the possible GPA and log
through GPA. Pay attention this reverse mapping is not guaranteed
to be unique, so we should log each possible GPA in this case.
This fix the failure of scp to guest during migration. In -next, we
will probably support passing GIOVA->GPA instead of GIOVA->HVA.
Fixes: 6b1e6cc7855b ("vhost: new device IOTLB API")
Reported-by: Jintack Lim <jintack@cs.columbia.edu>
Cc: Jintack Lim <jintack@cs.columbia.edu>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
The patch is needed for stable.
Changes from V1:
- return error instead of warn
---
drivers/vhost/net.c | 3 +-
drivers/vhost/vhost.c | 82 +++++++++++++++++++++++++++++++++++--------
drivers/vhost/vhost.h | 3 +-
3 files changed, 72 insertions(+), 16 deletions(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 36f3d0f49e60..bca86bf7189f 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -1236,7 +1236,8 @@ static void handle_rx(struct vhost_net *net)
if (nvq->done_idx > VHOST_NET_BATCH)
vhost_net_signal_used(nvq);
if (unlikely(vq_log))
- vhost_log_write(vq, vq_log, log, vhost_len);
+ vhost_log_write(vq, vq_log, log, vhost_len,
+ vq->iov, in);
total_len += vhost_len;
if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) {
vhost_poll_queue(&vq->poll);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 9f7942cbcbb2..ee095f08ffd4 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1733,11 +1733,70 @@ static int log_write(void __user *log_base,
return r;
}
+static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
+{
+ struct vhost_umem *umem = vq->umem;
+ struct vhost_umem_node *u;
+ u64 gpa;
+ int r;
+ bool hit = false;
+
+ list_for_each_entry(u, &umem->umem_list, link) {
+ if (u->userspace_addr < hva &&
+ u->userspace_addr + u->size >=
+ hva + len) {
+ gpa = u->start + hva - u->userspace_addr;
+ r = log_write(vq->log_base, gpa, len);
+ if (r < 0)
+ return r;
+ hit = true;
+ }
+ }
+
+ if (!hit)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len)
+{
+ struct iovec iov[64];
+ int i, ret;
+
+ if (!vq->iotlb)
+ return log_write(vq->log_base, vq->log_addr + used_offset, len);
+
+ ret = translate_desc(vq, (u64)(uintptr_t)vq->used + used_offset,
+ len, iov, 64, VHOST_ACCESS_WO);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ret; i++) {
+ ret = log_write_hva(vq, (u64)(uintptr_t)iov[i].iov_base,
+ iov[i].iov_len);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
- unsigned int log_num, u64 len)
+ unsigned int log_num, u64 len, struct iovec *iov, int count)
{
int i, r;
+ if (vq->iotlb) {
+ for (i = 0; i < count; i++) {
+ r = log_write_hva(vq, (u64)(uintptr_t)iov[i].iov_base,
+ iov[i].iov_len);
+ if (r < 0)
+ return r;
+ }
+ return 0;
+ }
+
/* Make sure data written is seen before log. */
smp_wmb();
for (i = 0; i < log_num; ++i) {
@@ -1769,9 +1828,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
smp_wmb();
/* Log used flag write. */
used = &vq->used->flags;
- log_write(vq->log_base, vq->log_addr +
- (used - (void __user *)vq->used),
- sizeof vq->used->flags);
+ log_used(vq, (used - (void __user *)vq->used),
+ sizeof vq->used->flags);
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
@@ -1789,9 +1847,8 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
smp_wmb();
/* Log avail event write */
used = vhost_avail_event(vq);
- log_write(vq->log_base, vq->log_addr +
- (used - (void __user *)vq->used),
- sizeof *vhost_avail_event(vq));
+ log_used(vq, (used - (void __user *)vq->used),
+ sizeof *vhost_avail_event(vq));
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
@@ -2191,10 +2248,8 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
/* Make sure data is seen before log. */
smp_wmb();
/* Log used ring entry write. */
- log_write(vq->log_base,
- vq->log_addr +
- ((void __user *)used - (void __user *)vq->used),
- count * sizeof *used);
+ log_used(vq, ((void __user *)used - (void __user *)vq->used),
+ count * sizeof *used);
}
old = vq->last_used_idx;
new = (vq->last_used_idx += count);
@@ -2236,9 +2291,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
/* Make sure used idx is seen before log. */
smp_wmb();
/* Log used index update. */
- log_write(vq->log_base,
- vq->log_addr + offsetof(struct vring_used, idx),
- sizeof vq->used->idx);
+ log_used(vq, offsetof(struct vring_used, idx),
+ sizeof vq->used->idx);
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 466ef7542291..1b675dad5e05 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -205,7 +205,8 @@ bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
- unsigned int log_num, u64 len);
+ unsigned int log_num, u64 len,
+ struct iovec *iov, int count);
int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
--
2.17.1
^ permalink raw reply related
* Re: __get_user slower than get_user (was Re: [RFC PATCH V3 0/5] Hi:)
From: Linus Torvalds @ 2019-01-09 5:19 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: KVM list, Netdev, Linux Kernel Mailing List, virtualization,
Dan Williams, David Miller
In-Reply-To: <20190108232459-mutt-send-email-mst@kernel.org>
On Tue, Jan 8, 2019 at 8:31 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>
> Linus, given that you just changed all users of access_ok anyway, do
> you still think that the access_ok() conversion to return a speculation
> sanitized pointer or NULL is too big a conversion?
I didn't actually change a single access_ok().
I changed the (very few) users of "user_access_begin()" to do an
access_ok() in them. There were 8 of them total.
It turns out that two of those cases (the strn*_user() ones) found
bugs in the implementation of access_ok() of two architectures, and
then looking at the others found that six more architectures also had
problems, but those weren't actually because of any access_ok()
changes, they were pre-existing issues. So we definitely had
unfortunate bugs in access_ok(), but they were mostly the benign kind
(ir the "use arguments twice - a real potential bug, but not one that
actually likely makes any difference to existing users)
Changing all 600+ users of access_ok() would be painful.
That said, one thing I *would* like to do is to just get rid of
__get_user() and __put_user() entirely. Or rather, just make them do
exactly the same thing that the normal "get_user()"/"put_user()"
functions do.
And then, _within_ the case of get_user()/put_user(), doing the
access_ok() as a data dependency rather than a lfence should be easy
enough.
Linus
^ permalink raw reply
* __get_user slower than get_user (was Re: [RFC PATCH V3 0/5] Hi:)
From: Michael S. Tsirkin @ 2019-01-09 4:31 UTC (permalink / raw)
To: Dan Williams
Cc: KVM list, Netdev, Linux Kernel Mailing List, virtualization,
Linus Torvalds, David Miller
In-Reply-To: <CAPcyv4iQMQxZC8ehr2OP8_rqpuCeSWn5xyKN64JSyfR8_r7eOg@mail.gmail.com>
On Mon, Jan 07, 2019 at 02:44:24PM -0800, Dan Williams wrote:
> On Mon, Jan 7, 2019 at 2:25 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Mon, Jan 07, 2019 at 01:39:15PM -0800, Dan Williams wrote:
> > > On Mon, Jan 7, 2019 at 6:11 AM Michael S. Tsirkin <mst@redhat.com> wrote:
> > > >
> > > > On Sun, Jan 06, 2019 at 11:15:20PM -0800, Dan Williams wrote:
> > > > > On Sun, Jan 6, 2019 at 8:17 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> > > > > >
> > > > > > On Mon, Jan 07, 2019 at 11:53:41AM +0800, Jason Wang wrote:
> > > > > > >
> > > > > > > On 2019/1/7 上午11:28, Michael S. Tsirkin wrote:
> > > > > > > > On Mon, Jan 07, 2019 at 10:19:03AM +0800, Jason Wang wrote:
> > > > > > > > > On 2019/1/3 上午4:47, Michael S. Tsirkin wrote:
> > > > > > > > > > On Sat, Dec 29, 2018 at 08:46:51PM +0800, Jason Wang wrote:
> > > > > > > > > > > This series tries to access virtqueue metadata through kernel virtual
> > > > > > > > > > > address instead of copy_user() friends since they had too much
> > > > > > > > > > > overheads like checks, spec barriers or even hardware feature
> > > > > > > > > > > toggling.
> > > > > > > > > > Will review, thanks!
> > > > > > > > > > One questions that comes to mind is whether it's all about bypassing
> > > > > > > > > > stac/clac. Could you please include a performance comparison with
> > > > > > > > > > nosmap?
> > > > > > > > > >
> > > > > > > > > On machine without SMAP (Sandy Bridge):
> > > > > > > > >
> > > > > > > > > Before: 4.8Mpps
> > > > > > > > >
> > > > > > > > > After: 5.2Mpps
> > > > > > > > OK so would you say it's really unsafe versus safe accesses?
> > > > > > > > Or would you say it's just a better written code?
> > > > > > >
> > > > > > >
> > > > > > > It's the effect of removing speculation barrier.
> > > > > >
> > > > > >
> > > > > > You mean __uaccess_begin_nospec introduced by
> > > > > > commit 304ec1b050310548db33063e567123fae8fd0301
> > > > > > ?
> > > > > >
> > > > > > So fundamentally we do access_ok checks when supplying
> > > > > > the memory table to the kernel thread, and we should
> > > > > > do the spec barrier there.
> > > > > >
> > > > > > Then we can just create and use a variant of uaccess macros that does
> > > > > > not include the barrier?
> > > > > >
> > > > > > Or, how about moving the barrier into access_ok?
> > > > > > This way repeated accesses with a single access_ok get a bit faster.
> > > > > > CC Dan Williams on this idea.
> > > > >
> > > > > It would be interesting to see how expensive re-doing the address
> > > > > limit check is compared to the speculation barrier. I.e. just switch
> > > > > vhost_get_user() to use get_user() rather than __get_user(). That will
> > > > > sanitize the pointer in the speculative path without a barrier.
> > > >
> > > > Hmm it's way cheaper even though IIRC it's measureable.
> > > > Jason, would you like to try?
> > > > Although frankly __get_user being slower than get_user feels very wrong.
> > > > Not yet sure what to do exactly but would you agree?
> > >
> > > Agree. __get_user() being faster than get_user() defeats the whole
> > > point of converting code paths to the access_ok() + __get_user()
> > > pattern.
> >
> > Did you mean the reverse?
>
> Hmm, no... I'll rephrase: __get_user() should have lower overhead than
> get_user().
Right ...
Linus, given that you just changed all users of access_ok anyway, do
you still think that the access_ok() conversion to return a speculation
sanitized pointer or NULL is too big a conversion?
It was previously discarded here:
https://lkml.org/lkml/2018/1/17/929
but at that point we didn't have numbers and there was an understandable
rush to ship something safe.
At this point I think that vhost can show very measureable gains from
this conversion.
Thanks,
--
MST
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* CFP: The 28th Int. ACM Symp. on High-Performance Parallel and Distributed Computing (HPDC'19) 2019
From: Ioan Raicu @ 2019-01-08 21:08 UTC (permalink / raw)
To: virtualization@lists.linux-foundation.org
[-- Attachment #1.1: Type: text/plain, Size: 6021 bytes --]
The 28th International ACM Symposium on
High-Performance Parallel and Distributed Computing (HPDC'19)
Phoenix, Arizona, United States on June 24-28, 2019
Sponsored by ACM SIGARCH
http://www.hpdc.org/2019/
http://www.hpdc.org/2019/papers/call-for-papers/hpdc2019-flyer.pdf
================================================================================
OVERVIEW
--------------------------------------------------------------------------------
The ACM International Symposium on High-Performance Parallel and Distributed
Computing (HPDC) is the premier annual conference for presenting the latest
research on the design, implementation, evaluation, and the use of parallel and
distributed systems for high-end computing. The 28th HPDC will take place in
Phoenix, Arizona, United States on June 24-28, 2019 as part of FCRC.
SCOPE AND TOPICS
--------------------------------------------------------------------------------
Submissions are welcomed on high-performance parallel and distributed computing
(HPDC) topics including but not limited to: clouds, clusters, grids, big data,
massively multicore, and extreme-scale computing systems. Experience reports of
operational deployments that provide significantly novel insights for future
research on HPDC applications and systems will also receive special
consideration.
In the context of high-performance parallel and distributed computing, the
topics of interest include, but are not limited to:
* Operating systems, networks, and architectures
* High performance runtime environments
* Massively multicore systems, including heterogeneous systems
* Datacenter technology, resource virtualization
* Programming languages, APIs, and system interoperation approaches
* File and storage systems, I/O, and data management
* Big data stacks and big data ecosystems
* Resource management and scheduling, including energy-aware techniques
* Performance modeling, analysis, and engineering
* Fault tolerance, reliability, and availability
* Operational guarantees, risk assessment, and management
* Emerging application areas that include cloud/edge computing and IoT
PAPER SUBMISSION GUIDELINES
--------------------------------------------------------------------------------
Authors are invited to submit technical papers of at most 12 pages in PDF
format, including figures and references. Papers should be formatted in the ACM
ACM Proceedings Style
(http://www.acm.org/publications/article-templates/proceedings-template.html)
and submitted via the conference web site. Submitted papers must be original
work that has not appeared in and is not under consideration for another
conference or a journal.
Submissions are now open here (https://hpdc19.hotcrp.com/).
DEADLINES
--------------------------------------------------------------------------------
Abstracts due: January 16, 2019
Papers due: January 23, 2019
Author notifications: March 25, 2019
Camera ready: April, 2019
Conference dates: June 24 - 28, 2019
ORGANIZING COMMITTEE
--------------------------------------------------------------------------------
General Chair:
Jon Weissman University of Minnesota, USA
Program Chairs:
Ali R. Butt Virginia Tech, USA
Evgenia Smirni College of William and Mary, USA
Local Chair:
Ming Zhao Arizona State University, USA
Program Committee:
George Amvrosiadis Carnegie Mellon University, USA
Christos Antonopoulos University of Thessaly, Greece
Ali Anwar IBM Research, USA
Michela Becchi North Carolina State University, USA
Kirk Cameron Virginia Tech, USA
Franck Cappello Argonne National Lab, USA
Giuliano Casale Imperial College London, U.K.
Abhishek Chandra University of Minnesota, USA
Ryan Chard Argonne National Laboratory, USA
Yue Cheng George Mason University, USA
Andrew A. Chien University of Chicago, USA
Peter Dinda Northwestern University, USA
Dick Epema Delft University of Technology, The Netherlands
David Eyres University of Otage, New Zealand
Renato Figueiredo University of Florida, USA
Liana Fong IBM, USA
José Fortes University of Florida, USA
Anshul Gandhi Stony Brook University, USA
Dimitrios Gizopoulos University of Athens, Greece
Kartik Gopalan Binghamton University, USA
Adriana Iamnitchi University of South Florida, USA
David Irwin University of Massachusets at Amherst, USA
Adwait Jog The College of William and Mary, USA
Changhee Jung Virginia Tech, USA
Jack Lange University of Pittsburgh, USA
Hang Liu UMASS-Lowell, USA
Jay Lofstead Sandia National Laboratories, USA
Xiaosong Ma Qatar Computing Research Institute, Qatar
Arthur Barney Maccabe Oak Ridge National Laboratory, USA
Carlos Maltzahn University of California, Santa Cruz, USA
Ningfang Mi Northeastern University, USA
Kathryn Mohror Lawrence Livermore National Laboratory, USA
Dimitrios Nikolopoulos Queen's University Belfast, UK
Karthik Pittabiraman University of British Columbia, Canada
Judy Qiu Indiana University, USA
M.Mustafa Rafique Rochester Institute of Technology, USA
Ioan Raicu Illinois Institute of Technology, USA
Lavanya Ramakrishnan Lawrence Berkeley National Laboratory, USA
Bin Ren College of William and Mary, USA
Matei Ripeanu University of British Columbia, Canada
Vasily Tarasov IBM Research, USA
Michela Taufer University of Tennessee
Douglas Thain University of Notre Dame, USA
Devesh Tiwari Northeastern University, USA
Ana Lucia Varbanescu University of Amsterdam, The Netherlands
Sudharshan Vazhkudai Oak Ridge National Laboratory, USA
Rich Wolski University of California at Santa Barbara, USA
Ji Xue Google, USA
Feng Yan University of Nevada Reno
Li Zhang IBM Research, USA
—
Ioan Raicu, Ph.D.
Associate Professor in CS at Illinois Institute of Technology
Guest Research Faculty in MCS at Argonne National Laboratory
http://www.cs.iit.edu/~iraicu/
http://datasys.cs.iit.edu/
[-- Attachment #1.2: Type: text/html, Size: 14936 bytes --]
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: kernel vhost demands an interrupt from guest when the ring is full in order to enable guest to submit new packets to the queue
From: Steven Luong (sluong) via Virtualization @ 2019-01-08 19:05 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Jerome Tollet (jtollet), Damjan Marion (damarion),
virtualization@lists.linux-foundation.org
In-Reply-To: <20181217191142-mutt-send-email-mst@kernel.org>
Michael,
Thank you very much for your help. I greatly appreciate it.
Steven
On 12/17/18, 4:16 PM, "Michael S. Tsirkin" <mst@redhat.com> wrote:
On Mon, Dec 17, 2018 at 11:56:59PM +0000, Steven Luong (sluong) wrote:
>
>
> On 12/17/18, 2:55 PM, "Michael S. Tsirkin" <mst@redhat.com> wrote:
>
> On Thu, Dec 13, 2018 at 11:24:28PM +0000, Steven Luong (sluong) via Virtualization wrote:
> > Folks,
> >
> >
> >
> > We came across a memory race condition between VPP vhost driver and the kernel
> > vhost. VPP is running a tap interface over vhost backend. In this case, VPP is
> > acting as the vhost driver mode and the kernel vhost is acting as the vhost
> > device mode.
> >
> >
> >
> > In the kernel vhost’s TX traffic direction which is VPP’s RX traffic direction,
> > kernel vhost is the producer and VPP is the consumer.
>
> Looking at vhost net kernel code, it seems to use the
> same terminology as virtio net.
> Can you pls clarify which ring number do you use 0 or 1?
>
> <SVL> 0. </SVL>
>
> I will assume ring 0 below.
>
>
>
> > Kernel vhost places
> > traffic in kernel vhost’s TX vring. VPP removes traffic in VPP’s RX vring.
>
>
> So VPP makes buffers available and vhost kernel uses them?
>
> <SVL> Correct. </SVL>
>
> > It
> > is inevitable that the vring may become full under heavy traffic and the kernel
> > vhost may have to stop and wait for the guest (VPP) to empty the vring and to
> > refill the vring with descriptors. When that case happens, kernel vhost clears
> > the bit in the vring’s used flag to request an interrupt/notification. Due to
> > shared memory race condition, VPP may miss the clearing of the vring’s used
> > flag from kernel vhost and didn’t send kernel vhost an interrupt after VPP
> > empties and refills the vring with new descriptors.
>
> So kernel vhost's wakeups are signalled through eventfd - I assume
> this is what you mean by an interrupt?
>
>
> To prevent the race that you describe, vhost has this code:
>
> /* OK, now we need to know about added descriptors. */
> if (!headcount) {
> if (unlikely(busyloop_intr)) {
> vhost_poll_queue(&vq->poll);
> } else if (unlikely(vhost_enable_notify(&net->dev, vq))) {
> /* They have slipped one in as we were
> * doing that: check again. */
> vhost_disable_notify(&net->dev, vq);
> continue;
> }
> /* Nothing new? Wait for eventfd to tell us
>
> So ring should be re-checked after notifications are enabled.
> If ring is no longer empty, vhost will proceed to handle the ring.
> This code has been around for many years.
>
> Thus if VPP doesn't work with it then I suspect it does something
> differently, e.g. is it possible that it is missing a memory
> barrier after writing out the available buffers and before
> checking the flags?
>
> <SVL> Can the race condition be avoided totally? Here is the scenario.
>
> t0: VPP refills the vring with new descriptors, not yet sets avail->idx to make it available to kernel vhost.
> t1: kernel vhost checks the vring, still sees no space available, but does not yet execute the line of code to clear the used->flags
> t2: vpp executes sfence, and sets avail->idx to make it available to kernel vhost
At this point you need a full memory barrier. E.g. mfence, or xor.
Otherwise the read can get re-ordered before the write.
> t3: vpp checks used->flags, it is still 1, vpp skips sending the interrupt
> t4: kernel vhost clears used->flags to indicate interrupt is required. But VPP just missed it.
fine but at this point kernel vhost will recheck using vhost_get_avail
and process the buffers. So the lack of notification isn't a problem:
bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
{
__virtio16 avail_idx;
int r;
if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY))
return false;
vq->used_flags &= ~VRING_USED_F_NO_NOTIFY;
if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) {
r = vhost_update_used_flags(vq);
if (r) {
vq_err(vq, "Failed to enable notification at %p: %d\n",
&vq->used->flags, r);
return false;
}
} else {
r = vhost_update_avail_event(vq, vq->avail_idx);
if (r) {
vq_err(vq, "Failed to update avail event index at %p: %d\n",
vhost_avail_event(vq), r);
return false;
}
}
/* They could have slipped one in as we were doing that: make
* sure it's written, then check again. */
smp_mb();
r = vhost_get_avail(vq, avail_idx, &vq->avail->idx);
if (r) {
vq_err(vq, "Failed to check avail idx at %p: %d\n",
&vq->avail->idx, r);
return false;
}
return vhost16_to_cpu(vq, avail_idx) != vq->avail_idx;
}
>The result is kernel vhost got stuck even though the vring is filled with new descriptors.
Shouldn't be. Maybe you are missing a fence before reading used->flags?
> Steven
>
> </SVL>
>
>
> > Unfortunately, this missed
> > notification causes the kernel vhost to be stuck because once the kernel vhost
> > is waiting for an interrupt/notification from the guest, only an interrupt/
> > notification from the guest can resume/re-enable the guest from submitting new
> > packets to the vring. This design seems vulnerable.
>
> The protocol right now relies on notifications never being lost.
>
> I can imagine an alternative where device also re-checks
> the rings periodically, but that would involve running
> timers host side which is only possible if there's a
> free processor that can handle them. Further,
> it will still lead to stalls and packet drops, which will
> be harder to debug.
>
> That's just my $.02, pls feel free to take it with the virtio tc
> maybe others will feel differently.
>
> > Should the kernel vhost
> > totally depend on the notification from the guest? Quoting the text from
> >
> >
> >
> > http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html
> >
> >
> >
> > /* The device uses this in used->flags to advise the driver: don’t kick me
> > * when you add a buffer. It’s unreliable, so it’s simply an
> > * optimization. */
> > #define VIRTQ_USED_F_NO_NOTIFY 1
> >
> >
> >
> > I interpret that the notification is simply an optimization, not a reliable
> > notification mechanism.
>
> What was meant I think is that suppression is unreliable.
>
> >So the kernel vhost should not bet the farm on it.
> >
> >
> >
> > We encounter the same race condition in kernel vhost’s RX traffic direction
> > which causes the kernel vhost to be stuck due to missed interrupt/notification
> > although it is less frequent.
>
>
> For the reverse direction the spec actually has some pseudo-code and a suggestion
> about handling that race:
>
> For optimal performance, a driver MAY disable used buffer notifications while processing the used
> ring, but beware the problem of missing notifications between emptying the ring and reenabling no-
> tifications. This is usually handled by re-checking for more used buffers after notifications are re-
> enabled:
>
> virtq_disable_used_buffer_notifications(vq);
> for (;;) {
> if (vq->last_seen_used != le16_to_cpu(virtq->used.idx)) {
> virtq_enable_used_buffer_notifications(vq);
> mb();
> if (vq->last_seen_used != le16_to_cpu(virtq->used.idx))
> break;
> virtq_disable_used_buffer_notifications(vq);
> }
> struct virtq_used_elem *e = virtq.used->ring[vq->last_seen_used%vsz];
> process_buffer(e);
> vq->last_seen_used++;
>
>
>
> >
> >
> > Steven
> >
>
> > _______________________________________________
> > Virtualization mailing list
> > Virtualization@lists.linux-foundation.org
> > https://lists.linuxfoundation.org/mailman/listinfo/virtualization
>
>
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH RFC 1/4] include/linux/compiler*.h: fix OPTIMIZER_HIDE_VAR
From: Michael S. Tsirkin @ 2019-01-08 18:50 UTC (permalink / raw)
To: Nick Desaulniers
Cc: Andrea Parri, Peter Zijlstra, Akira Yokosawa, Will Deacon,
virtualization, David Howells, linux-arch, linux-sparse,
Alan Stern, Paul E. McKenney, Boqun Feng, Daniel Lustig,
Nicholas Piggin, Luc Maranget, Eli Friedman, Jade Alglave, netdev,
LKML, Eric Christopher, Miguel Ojeda, Joe Perches, Linus Torvalds,
Luc Van Oostenryck
In-Reply-To: <CAKwvOdk3b6mnpTEEyY-JFrej8K12w9oTMLqi7q5aNiRMyJo6Ow@mail.gmail.com>
On Tue, Jan 08, 2019 at 09:44:28AM -0800, Nick Desaulniers wrote:
> Thanks for the patch and sorry for the delay; was totally unplugged
> for the holidays.
> On Wed, Jan 2, 2019 at 12:57 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > Since commit 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h
> > mutually exclusive") clang no longer reuses the OPTIMIZER_HIDE_VAR macro
> > from compiler-gcc - instead it gets the version in
> > include/linux/compiler.h. Unfortunately that version doesn't actually
> > prevent compiler from optimizing out the variable.
>
> Good catch. Did you find this via eyeballing the code, a test, or some
> other way?
eyeballing
> >
> > Fix up by moving the macro out from compiler-gcc.h to compiler.h.
> > Compilers without incline asm support will keep working
> > since it's protected by an ifdef.
> >
> > Also fix up comments to match reality since we are no longer overriding
> > any macros.
> >
> > Build-tested with gcc and clang.
> >
> > Fixes: 815f0ddb346c ("include/linux/compiler*.h: make compiler-*.h mutually exclusive")
> > Cc: Eli Friedman <efriedma@codeaurora.org>
> > Cc: Joe Perches <joe@perches.com>
> > Cc: Nick Desaulniers <ndesaulniers@google.com>
> > Cc: Linus Torvalds <torvalds@linux-foundation.org>
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>
> Also for more context, see:
> commit 7829fb09a2b4 ("lib: make memzero_explicit more robust against
> dead store elimination")
Interesting. That added this text:
* while gcc behavior gets along with a normal
* barrier(), llvm needs an explicit input variable to be assumed
* clobbered.
however:
#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
So no explicit variable is clobbered.
Weird isn't it?
> > ---
> > include/linux/compiler-clang.h | 5 ++---
> > include/linux/compiler-gcc.h | 4 ----
> > include/linux/compiler-intel.h | 4 +---
> > include/linux/compiler.h | 4 +++-
> > 4 files changed, 6 insertions(+), 11 deletions(-)
> >
> > diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h
> > index 3e7dafb3ea80..7ddaeb5182e3 100644
> > --- a/include/linux/compiler-clang.h
> > +++ b/include/linux/compiler-clang.h
> > @@ -3,9 +3,8 @@
> > #error "Please don't include <linux/compiler-clang.h> directly, include <linux/compiler.h> instead."
> > #endif
> >
> > -/* Some compiler specific definitions are overwritten here
> > - * for Clang compiler
> > - */
> > +/* Compiler specific definitions for Clang compiler */
> > +
> > #define uninitialized_var(x) x = *(&(x))
> >
> > /* same as gcc, this was present in clang-2.6 so we can assume it works
> > diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
> > index 2010493e1040..72054d9f0eaa 100644
> > --- a/include/linux/compiler-gcc.h
> > +++ b/include/linux/compiler-gcc.h
> > @@ -58,10 +58,6 @@
> > (typeof(ptr)) (__ptr + (off)); \
> > })
> >
> > -/* Make the optimizer believe the variable can be manipulated arbitrarily. */
> > -#define OPTIMIZER_HIDE_VAR(var) \
> > - __asm__ ("" : "=r" (var) : "0" (var))
> > -
> > /*
> > * A trick to suppress uninitialized variable warning without generating any
> > * code
> > diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h
> > index 517bd14e1222..b17f3cd18334 100644
> > --- a/include/linux/compiler-intel.h
> > +++ b/include/linux/compiler-intel.h
> > @@ -5,9 +5,7 @@
> >
> > #ifdef __ECC
> >
> > -/* Some compiler specific definitions are overwritten here
> > - * for Intel ECC compiler
> > - */
> > +/* Compiler specific definitions for Intel ECC compiler */
> >
> > #include <asm/intrinsics.h>
> >
> > diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> > index 06396c1cf127..1ad367b4cd8d 100644
> > --- a/include/linux/compiler.h
> > +++ b/include/linux/compiler.h
> > @@ -152,7 +152,9 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
> > #endif
> >
> > #ifndef OPTIMIZER_HIDE_VAR
> > -#define OPTIMIZER_HIDE_VAR(var) barrier()
> > +/* Make the optimizer believe the variable can be manipulated arbitrarily. */
> > +#define OPTIMIZER_HIDE_VAR(var) \
> > + __asm__ ("" : "=r" (var) : "0" (var))
> > #endif
>
> This should be fine, thanks for the cleanup! For now, we're not yet
> confident to turn on Clang's integrated assembler for the kernel, but
> I'll make sure to revisit this should we, in case Clang is then able
> to optimize this out.
> + Eric, who might know of a better trick for what we're trying to
> accomplish with this macro.
>
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
>
> + Miguel
> Miguel, would you mind taking this into your compiler-attributes tree?
> --
> Thanks,
> ~Nick Desaulniers
^ permalink raw reply
* Re: [RFC PATCH V3 0/5] Hi:
From: Jason Wang @ 2019-01-08 11:42 UTC (permalink / raw)
To: Michael S. Tsirkin, Dan Williams
Cc: Netdev, David Miller, Linux Kernel Mailing List, KVM list,
virtualization
In-Reply-To: <20190107084853-mutt-send-email-mst@kernel.org>
On 2019/1/7 下午10:11, Michael S. Tsirkin wrote:
> On Sun, Jan 06, 2019 at 11:15:20PM -0800, Dan Williams wrote:
>> On Sun, Jan 6, 2019 at 8:17 PM Michael S. Tsirkin <mst@redhat.com> wrote:
>>> On Mon, Jan 07, 2019 at 11:53:41AM +0800, Jason Wang wrote:
>>>> On 2019/1/7 上午11:28, Michael S. Tsirkin wrote:
>>>>> On Mon, Jan 07, 2019 at 10:19:03AM +0800, Jason Wang wrote:
>>>>>> On 2019/1/3 上午4:47, Michael S. Tsirkin wrote:
>>>>>>> On Sat, Dec 29, 2018 at 08:46:51PM +0800, Jason Wang wrote:
>>>>>>>> This series tries to access virtqueue metadata through kernel virtual
>>>>>>>> address instead of copy_user() friends since they had too much
>>>>>>>> overheads like checks, spec barriers or even hardware feature
>>>>>>>> toggling.
>>>>>>> Will review, thanks!
>>>>>>> One questions that comes to mind is whether it's all about bypassing
>>>>>>> stac/clac. Could you please include a performance comparison with
>>>>>>> nosmap?
>>>>>>>
>>>>>> On machine without SMAP (Sandy Bridge):
>>>>>>
>>>>>> Before: 4.8Mpps
>>>>>>
>>>>>> After: 5.2Mpps
>>>>> OK so would you say it's really unsafe versus safe accesses?
>>>>> Or would you say it's just a better written code?
>>>>
>>>> It's the effect of removing speculation barrier.
>>>
>>> You mean __uaccess_begin_nospec introduced by
>>> commit 304ec1b050310548db33063e567123fae8fd0301
>>> ?
>>>
>>> So fundamentally we do access_ok checks when supplying
>>> the memory table to the kernel thread, and we should
>>> do the spec barrier there.
>>>
>>> Then we can just create and use a variant of uaccess macros that does
>>> not include the barrier?
>>>
>>> Or, how about moving the barrier into access_ok?
>>> This way repeated accesses with a single access_ok get a bit faster.
>>> CC Dan Williams on this idea.
>> It would be interesting to see how expensive re-doing the address
>> limit check is compared to the speculation barrier. I.e. just switch
>> vhost_get_user() to use get_user() rather than __get_user(). That will
>> sanitize the pointer in the speculative path without a barrier.
> Hmm it's way cheaper even though IIRC it's measureable.
> Jason, would you like to try?
0.5% regression after using get_user()/put_user()/...
> Although frankly __get_user being slower than get_user feels very wrong.
> Not yet sure what to do exactly but would you agree?
>
>
>> I recall we had a convert access_ok() discussion with this result here:
>>
>> https://lkml.org/lkml/2018/1/17/929
> Sorry let me try to clarify. IIUC speculating access_ok once
> is harmless. As Linus said the problem is with "_subsequent_
> accesses that can then be used to perturb the cache".
>
> Thus:
>
> 1. if (!access_ok)
> 2. return
> 3. get_user
> 4. if (!access_ok)
> 5. return
> 6. get_user
>
> Your proposal that Linus nacked was to effectively add a barrier after
> lines 2 and 5 (also using the array_index_nospec trick for speed),
> right? Unfortunately that needs a big API change.
>
> I am asking about adding barrier_nospec within access_ok.
> Thus effectively before lines 1 and 4.
> access_ok will be slower but after all the point of access_ok is
> to then access the same memory multiple times.
> So we should be making __get_user faster and access_ok slower ...
And the barrier_nospec() was completely necessary if you want to do
write instead read.
Thanks
>
>> ...but it sounds like you are proposing a smaller scope fixup for the
>> vhost use case? Something like barrier_nospec() in the success path
>> for all vhost access_ok() checks and then a get_user() variant that
>> disables the barrier.
> Maybe we'll have to. Except I hope vhost won't end up being the
> only user otherwise it will be hard to maintain.
>
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* [PATCH v2 15/15] drm/bochs: reserve bo for pin/unpin
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
The buffer object must be reserved before calling
ttm_bo_validate for pinning/unpinning.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
drivers/gpu/drm/bochs/bochs_mm.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index cfe061c25f..970a591908 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -223,7 +223,11 @@ int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag)
bochs_ttm_placement(bo, pl_flag);
for (i = 0; i < bo->placement.num_placement; i++)
bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+ ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+ if (ret)
+ return ret;
ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
+ ttm_bo_unreserve(&bo->bo);
if (ret)
return ret;
@@ -247,7 +251,11 @@ int bochs_bo_unpin(struct bochs_bo *bo)
for (i = 0; i < bo->placement.num_placement; i++)
bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
+ ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+ if (ret)
+ return ret;
ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
+ ttm_bo_unreserve(&bo->bo);
if (ret)
return ret;
--
2.9.3
^ permalink raw reply related
* [PATCH v2 14/15] drm/bochs: move remaining fb bits to kms
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU, open list
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
bochs_fbdev.c is almost empty now. Move the remaining framebuffer bits
over to bochs_kms.c. Pure code motion. No functional change.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_fbdev.c | 29 -----------------------------
drivers/gpu/drm/bochs/bochs_kms.c | 17 +++++++++++++++++
drivers/gpu/drm/bochs/Makefile | 2 +-
3 files changed, 18 insertions(+), 30 deletions(-)
delete mode 100644 drivers/gpu/drm/bochs/bochs_fbdev.c
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
deleted file mode 100644
index 7cac3f5253..0000000000
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "bochs.h"
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-
-/* ---------------------------------------------------------------------- */
-
-static struct drm_framebuffer *
-bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
- const struct drm_mode_fb_cmd2 *mode_cmd)
-{
- if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
- mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
- return ERR_PTR(-EINVAL);
-
- return drm_gem_fb_create(dev, file, mode_cmd);
-}
-
-const struct drm_mode_config_funcs bochs_mode_funcs = {
- .fb_create = bochs_gem_fb_create,
- .atomic_check = drm_atomic_helper_check,
- .atomic_commit = drm_atomic_helper_commit,
-};
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index fc856a02a2..e9d5dbc346 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -9,6 +9,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_gem_framebuffer_helper.h>
static int defx = 1024;
static int defy = 768;
@@ -256,6 +257,22 @@ static void bochs_connector_init(struct drm_device *dev)
}
}
+static struct drm_framebuffer *
+bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
+ mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
+ return ERR_PTR(-EINVAL);
+
+ return drm_gem_fb_create(dev, file, mode_cmd);
+}
+
+const struct drm_mode_config_funcs bochs_mode_funcs = {
+ .fb_create = bochs_gem_fb_create,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
int bochs_kms_init(struct bochs_device *bochs)
{
diff --git a/drivers/gpu/drm/bochs/Makefile b/drivers/gpu/drm/bochs/Makefile
index 98ef60a19e..e9e0f8f5eb 100644
--- a/drivers/gpu/drm/bochs/Makefile
+++ b/drivers/gpu/drm/bochs/Makefile
@@ -1,3 +1,3 @@
-bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_fbdev.o bochs_hw.o
+bochs-drm-y := bochs_drv.o bochs_mm.o bochs_kms.o bochs_hw.o
obj-$(CONFIG_DRM_BOCHS) += bochs-drm.o
--
2.9.3
^ permalink raw reply related
* [PATCH v2 13/15] drm/bochs: drop old fbdev emulation code
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Not needed any more, bochs uses the generic emulation now.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs.h | 9 ---
drivers/gpu/drm/bochs/bochs_drv.c | 6 --
drivers/gpu/drm/bochs/bochs_fbdev.c | 137 ------------------------------------
3 files changed, 152 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index df9ff6425d..1ecabd2b78 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -80,12 +80,6 @@ struct bochs_device {
struct ttm_bo_device bdev;
bool initialized;
} ttm;
-
- /* fbdev */
- struct {
- struct drm_framebuffer *fb;
- struct drm_fb_helper helper;
- } fb;
};
struct bochs_bo {
@@ -161,7 +155,4 @@ int bochs_kms_init(struct bochs_device *bochs);
void bochs_kms_fini(struct bochs_device *bochs);
/* bochs_fbdev.c */
-int bochs_fbdev_init(struct bochs_device *bochs);
-void bochs_fbdev_fini(struct bochs_device *bochs);
-
extern const struct drm_mode_config_funcs bochs_mode_funcs;
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index 350e34cf2c..4f78e42686 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -106,12 +106,9 @@ static int bochs_pm_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
- struct bochs_device *bochs = drm_dev->dev_private;
drm_kms_helper_poll_disable(drm_dev);
- drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 1);
-
return 0;
}
@@ -119,12 +116,9 @@ static int bochs_pm_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct drm_device *drm_dev = pci_get_drvdata(pdev);
- struct bochs_device *bochs = drm_dev->dev_private;
drm_helper_resume_force_mode(drm_dev);
- drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 0);
-
drm_kms_helper_poll_enable(drm_dev);
return 0;
}
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index 92feb817ff..7cac3f5253 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -11,132 +11,6 @@
/* ---------------------------------------------------------------------- */
-static int bochsfb_mmap(struct fb_info *info,
- struct vm_area_struct *vma)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct bochs_bo *bo = gem_to_bochs_bo(fb_helper->fb->obj[0]);
-
- return ttm_fbdev_mmap(vma, &bo->bo);
-}
-
-static struct fb_ops bochsfb_ops = {
- .owner = THIS_MODULE,
- DRM_FB_HELPER_DEFAULT_OPS,
- .fb_fillrect = drm_fb_helper_cfb_fillrect,
- .fb_copyarea = drm_fb_helper_cfb_copyarea,
- .fb_imageblit = drm_fb_helper_cfb_imageblit,
- .fb_mmap = bochsfb_mmap,
-};
-
-static int bochsfb_create_object(struct bochs_device *bochs,
- const struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_gem_object **gobj_p)
-{
- struct drm_device *dev = bochs->dev;
- struct drm_gem_object *gobj;
- u32 size;
- int ret = 0;
-
- size = mode_cmd->pitches[0] * mode_cmd->height;
- ret = bochs_gem_create(dev, size, true, &gobj);
- if (ret)
- return ret;
-
- *gobj_p = gobj;
- return ret;
-}
-
-static int bochsfb_create(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct bochs_device *bochs =
- container_of(helper, struct bochs_device, fb.helper);
- struct fb_info *info;
- struct drm_framebuffer *fb;
- struct drm_mode_fb_cmd2 mode_cmd;
- struct drm_gem_object *gobj = NULL;
- struct bochs_bo *bo = NULL;
- int size, ret;
-
- if (sizes->surface_bpp != 32)
- return -EINVAL;
-
- mode_cmd.width = sizes->surface_width;
- mode_cmd.height = sizes->surface_height;
- mode_cmd.pitches[0] = sizes->surface_width * 4;
- mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888;
- size = mode_cmd.pitches[0] * mode_cmd.height;
-
- /* alloc, pin & map bo */
- ret = bochsfb_create_object(bochs, &mode_cmd, &gobj);
- if (ret) {
- DRM_ERROR("failed to create fbcon backing object %d\n", ret);
- return ret;
- }
-
- bo = gem_to_bochs_bo(gobj);
-
- ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
- if (ret)
- return ret;
-
- ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
- if (ret) {
- DRM_ERROR("failed to pin fbcon\n");
- ttm_bo_unreserve(&bo->bo);
- return ret;
- }
-
- ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
- &bo->kmap);
- if (ret) {
- DRM_ERROR("failed to kmap fbcon\n");
- ttm_bo_unreserve(&bo->bo);
- return ret;
- }
-
- ttm_bo_unreserve(&bo->bo);
-
- /* init fb device */
- info = drm_fb_helper_alloc_fbi(helper);
- if (IS_ERR(info)) {
- DRM_ERROR("Failed to allocate fbi: %ld\n", PTR_ERR(info));
- return PTR_ERR(info);
- }
-
- info->par = &bochs->fb.helper;
-
- fb = drm_gem_fbdev_fb_create(bochs->dev, sizes, 0, gobj, NULL);
- if (IS_ERR(fb)) {
- DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb));
- return PTR_ERR(fb);
- }
-
- /* setup helper */
- bochs->fb.helper.fb = fb;
-
- strcpy(info->fix.id, "bochsdrmfb");
-
- info->fbops = &bochsfb_ops;
-
- drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
- drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width,
- sizes->fb_height);
-
- info->screen_base = bo->kmap.virtual;
- info->screen_size = size;
-
- drm_vma_offset_remove(&bo->bo.bdev->vma_manager, &bo->bo.vma_node);
- info->fix.smem_start = 0;
- info->fix.smem_len = size;
- return 0;
-}
-
-static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
- .fb_probe = bochsfb_create,
-};
-
static struct drm_framebuffer *
bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
const struct drm_mode_fb_cmd2 *mode_cmd)
@@ -153,14 +27,3 @@ const struct drm_mode_config_funcs bochs_mode_funcs = {
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
-
-int bochs_fbdev_init(struct bochs_device *bochs)
-{
- return drm_fb_helper_fbdev_setup(bochs->dev, &bochs->fb.helper,
- &bochs_fb_helper_funcs, 32, 1);
-}
-
-void bochs_fbdev_fini(struct bochs_device *bochs)
-{
- drm_fb_helper_fbdev_teardown(bochs->dev);
-}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 12/15] drm/bochs: switch to generic drm fbdev emulation
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
drivers/gpu/drm/bochs/bochs_drv.c | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index a9c7140e3b..350e34cf2c 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -16,10 +16,6 @@ static int bochs_modeset = -1;
module_param_named(modeset, bochs_modeset, int, 0444);
MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
-static bool enable_fbdev = true;
-module_param_named(fbdev, enable_fbdev, bool, 0444);
-MODULE_PARM_DESC(fbdev, "register fbdev device");
-
/* ---------------------------------------------------------------------- */
/* drm interface */
@@ -27,7 +23,6 @@ static void bochs_unload(struct drm_device *dev)
{
struct bochs_device *bochs = dev->dev_private;
- bochs_fbdev_fini(bochs);
bochs_kms_fini(bochs);
bochs_mm_fini(bochs);
bochs_hw_fini(dev);
@@ -58,9 +53,6 @@ static int bochs_load(struct drm_device *dev)
if (ret)
goto err;
- if (enable_fbdev)
- bochs_fbdev_init(bochs);
-
return 0;
err:
@@ -178,6 +170,7 @@ static int bochs_pci_probe(struct pci_dev *pdev,
if (ret)
goto err_unload;
+ drm_fbdev_generic_setup(dev, 32);
return ret;
err_unload:
--
2.9.3
^ permalink raw reply related
* [PATCH v2 11/15] drm/bochs: add basic prime support
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Generic framebuffer emulation needs this.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs.h | 11 +++++++
drivers/gpu/drm/bochs/bochs_drv.c | 15 +++++++++-
drivers/gpu/drm/bochs/bochs_mm.c | 63 +++++++++++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index d0d474e06f..df9ff6425d 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -145,6 +145,17 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag);
int bochs_bo_unpin(struct bochs_bo *bo);
+int bochs_gem_prime_pin(struct drm_gem_object *obj);
+void bochs_gem_prime_unpin(struct drm_gem_object *obj);
+struct sg_table *bochs_gem_prime_get_sg_table(struct drm_gem_object *obj);
+struct drm_gem_object *bochs_gem_prime_import_sg_table(
+ struct drm_device *dev, struct dma_buf_attachment *attach,
+ struct sg_table *sgt);
+void *bochs_gem_prime_vmap(struct drm_gem_object *obj);
+void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int bochs_gem_prime_mmap(struct drm_gem_object *obj,
+ struct vm_area_struct *vma);
+
/* bochs_kms.c */
int bochs_kms_init(struct bochs_device *bochs);
void bochs_kms_fini(struct bochs_device *bochs);
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index 278f9d2e7f..a9c7140e3b 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -81,7 +81,8 @@ static const struct file_operations bochs_fops = {
};
static struct drm_driver bochs_driver = {
- .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
+ DRIVER_PRIME,
.fops = &bochs_fops,
.name = "bochs-drm",
.desc = "bochs dispi vga interface (qemu stdvga)",
@@ -91,6 +92,18 @@ static struct drm_driver bochs_driver = {
.gem_free_object_unlocked = bochs_gem_free_object,
.dumb_create = bochs_dumb_create,
.dumb_map_offset = bochs_dumb_mmap_offset,
+
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+ .gem_prime_export = drm_gem_prime_export,
+ .gem_prime_import = drm_gem_prime_import,
+ .gem_prime_pin = bochs_gem_prime_pin,
+ .gem_prime_unpin = bochs_gem_prime_unpin,
+ .gem_prime_get_sg_table = bochs_gem_prime_get_sg_table,
+ .gem_prime_import_sg_table = bochs_gem_prime_import_sg_table,
+ .gem_prime_vmap = bochs_gem_prime_vmap,
+ .gem_prime_vunmap = bochs_gem_prime_vunmap,
+ .gem_prime_mmap = bochs_gem_prime_mmap,
};
/* ---------------------------------------------------------------------- */
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index 5a0e092847..cfe061c25f 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -387,3 +387,66 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
drm_gem_object_put_unlocked(obj);
return 0;
}
+
+/* ---------------------------------------------------------------------- */
+
+int bochs_gem_prime_pin(struct drm_gem_object *obj)
+{
+ struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+ return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
+}
+
+void bochs_gem_prime_unpin(struct drm_gem_object *obj)
+{
+ struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+ bochs_bo_unpin(bo);
+}
+
+struct sg_table *bochs_gem_prime_get_sg_table(struct drm_gem_object *obj)
+{
+ WARN_ONCE(1, "not implemented");
+ return ERR_PTR(-ENODEV);
+}
+
+struct drm_gem_object *bochs_gem_prime_import_sg_table(
+ struct drm_device *dev, struct dma_buf_attachment *attach,
+ struct sg_table *table)
+{
+ WARN_ONCE(1, "not implemented");
+ return ERR_PTR(-ENODEV);
+}
+
+void *bochs_gem_prime_vmap(struct drm_gem_object *obj)
+{
+ struct bochs_bo *bo = gem_to_bochs_bo(obj);
+ bool is_iomem;
+ int ret;
+
+ ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
+ if (ret)
+ return NULL;
+ ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+ if (ret) {
+ bochs_bo_unpin(bo);
+ return NULL;
+ }
+ return ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
+}
+
+void bochs_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
+{
+ struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+ ttm_bo_kunmap(&bo->kmap);
+ bochs_bo_unpin(bo);
+}
+
+int bochs_gem_prime_mmap(struct drm_gem_object *obj,
+ struct vm_area_struct *vma)
+{
+ struct bochs_bo *bo = gem_to_bochs_bo(obj);
+
+ return ttm_fbdev_mmap(vma, &bo->bo);
+}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 10/15] drm/bochs: drop unused gpu_addr arg from bochs_bo_pin()
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
It's always NULL, so just remove it.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs.h | 2 +-
drivers/gpu/drm/bochs/bochs_fbdev.c | 2 +-
drivers/gpu/drm/bochs/bochs_kms.c | 2 +-
drivers/gpu/drm/bochs/bochs_mm.c | 11 +----------
4 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index 4dc1b6384e..d0d474e06f 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -142,7 +142,7 @@ int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
uint32_t handle, uint64_t *offset);
-int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr);
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag);
int bochs_bo_unpin(struct bochs_bo *bo);
/* bochs_kms.c */
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index d9f3d42999..92feb817ff 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -81,7 +81,7 @@ static int bochsfb_create(struct drm_fb_helper *helper,
if (ret)
return ret;
- ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+ ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
if (ret) {
DRM_ERROR("failed to pin fbcon\n");
ttm_bo_unreserve(&bo->bo);
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 85ada2d097..fc856a02a2 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -96,7 +96,7 @@ static int bochs_plane_prepare_fb(struct drm_plane *plane,
if (!new_state->fb)
return 0;
bo = gem_to_bochs_bo(new_state->fb->obj[0]);
- return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+ return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM);
}
static void bochs_plane_cleanup_fb(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/bochs/bochs_mm.c b/drivers/gpu/drm/bochs/bochs_mm.c
index 0980411e41..5a0e092847 100644
--- a/drivers/gpu/drm/bochs/bochs_mm.c
+++ b/drivers/gpu/drm/bochs/bochs_mm.c
@@ -210,20 +210,13 @@ static void bochs_ttm_placement(struct bochs_bo *bo, int domain)
bo->placement.num_busy_placement = c;
}
-static inline u64 bochs_bo_gpu_offset(struct bochs_bo *bo)
-{
- return bo->bo.offset;
-}
-
-int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr)
+int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag)
{
struct ttm_operation_ctx ctx = { false, false };
int i, ret;
if (bo->pin_count) {
bo->pin_count++;
- if (gpu_addr)
- *gpu_addr = bochs_bo_gpu_offset(bo);
return 0;
}
@@ -235,8 +228,6 @@ int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr)
return ret;
bo->pin_count = 1;
- if (gpu_addr)
- *gpu_addr = bochs_bo_gpu_offset(bo);
return 0;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 09/15] drm/bochs: remove old bochs_crtc_* functions
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Remove the old, now unused crtc callbacks.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_kms.c | 81 ---------------------------------------
1 file changed, 81 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index f39e291245..85ada2d097 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -20,74 +20,6 @@ MODULE_PARM_DESC(defy, "default y resolution");
/* ---------------------------------------------------------------------- */
-static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- default:
- return;
- }
-}
-
-static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct bochs_device *bochs =
- container_of(crtc, struct bochs_device, crtc);
- struct bochs_bo *bo;
- u64 gpu_addr = 0;
- int ret;
-
- if (old_fb) {
- bo = gem_to_bochs_bo(old_fb->obj[0]);
- ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
- if (ret) {
- DRM_ERROR("failed to reserve old_fb bo\n");
- } else {
- bochs_bo_unpin(bo);
- ttm_bo_unreserve(&bo->bo);
- }
- }
-
- if (WARN_ON(crtc->primary->fb == NULL))
- return -EINVAL;
-
- bo = gem_to_bochs_bo(crtc->primary->fb->obj[0]);
- ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
- if (ret)
- return ret;
-
- ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
- if (ret) {
- ttm_bo_unreserve(&bo->bo);
- return ret;
- }
-
- ttm_bo_unreserve(&bo->bo);
- bochs_hw_setbase(bochs, x, y, gpu_addr);
- return 0;
-}
-
-static int bochs_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y, struct drm_framebuffer *old_fb)
-{
- struct bochs_device *bochs =
- container_of(crtc, struct bochs_device, crtc);
-
- if (WARN_ON(crtc->primary->fb == NULL))
- return -EINVAL;
-
- bochs_hw_setmode(bochs, mode);
- bochs_hw_setformat(bochs, crtc->primary->fb->format);
- bochs_crtc_mode_set_base(crtc, x, y, old_fb);
- return 0;
-}
-
static void bochs_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
struct bochs_device *bochs =
@@ -96,14 +28,6 @@ static void bochs_crtc_mode_set_nofb(struct drm_crtc *crtc)
bochs_hw_setmode(bochs, &crtc->mode);
}
-static void bochs_crtc_prepare(struct drm_crtc *crtc)
-{
-}
-
-static void bochs_crtc_commit(struct drm_crtc *crtc)
-{
-}
-
static void bochs_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -138,12 +62,7 @@ static const struct drm_crtc_funcs bochs_crtc_funcs = {
};
static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
- .dpms = bochs_crtc_dpms,
- .mode_set = bochs_crtc_mode_set,
- .mode_set_base = bochs_crtc_mode_set_base,
.mode_set_nofb = bochs_crtc_mode_set_nofb,
- .prepare = bochs_crtc_prepare,
- .commit = bochs_crtc_commit,
.atomic_enable = bochs_crtc_atomic_enable,
.atomic_flush = bochs_crtc_atomic_flush,
};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 08/15] drm/bochs: atomic: set DRIVER_ATOMIC
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Conversion to atomic modesetting, final step.
Set the DRIVER_ATOMIC flag.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_drv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c
index f3dd66ae99..278f9d2e7f 100644
--- a/drivers/gpu/drm/bochs/bochs_drv.c
+++ b/drivers/gpu/drm/bochs/bochs_drv.c
@@ -81,7 +81,7 @@ static const struct file_operations bochs_fops = {
};
static struct drm_driver bochs_driver = {
- .driver_features = DRIVER_GEM | DRIVER_MODESET,
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
.fops = &bochs_fops,
.name = "bochs-drm",
.desc = "bochs dispi vga interface (qemu stdvga)",
--
2.9.3
^ permalink raw reply related
* [PATCH v2 07/15] drm/bochs: atomic: use atomic page_flip helper
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Conversion to atomic modesetting, step five.
Use atomic page_flip helper for crtc.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_kms.c | 23 +----------------------
1 file changed, 1 insertion(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 3c91ff652b..f39e291245 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -104,27 +104,6 @@ static void bochs_crtc_commit(struct drm_crtc *crtc)
{
}
-static int bochs_crtc_page_flip(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event,
- uint32_t page_flip_flags,
- struct drm_modeset_acquire_ctx *ctx)
-{
- struct bochs_device *bochs =
- container_of(crtc, struct bochs_device, crtc);
- struct drm_framebuffer *old_fb = crtc->primary->fb;
- unsigned long irqflags;
-
- drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
- bochs_crtc_mode_set_base(crtc, 0, 0, old_fb);
- if (event) {
- spin_lock_irqsave(&bochs->dev->event_lock, irqflags);
- drm_crtc_send_vblank_event(crtc, event);
- spin_unlock_irqrestore(&bochs->dev->event_lock, irqflags);
- }
- return 0;
-}
-
static void bochs_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -152,7 +131,7 @@ static void bochs_crtc_atomic_flush(struct drm_crtc *crtc,
static const struct drm_crtc_funcs bochs_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.destroy = drm_crtc_cleanup,
- .page_flip = bochs_crtc_page_flip,
+ .page_flip = drm_atomic_helper_page_flip,
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
--
2.9.3
^ permalink raw reply related
* [PATCH v2 06/15] drm/bochs: atomic: use atomic set_config helper
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Conversion to atomic modesetting, step four.
Use atomic set_config helper for crtc.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_kms.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 570f761ec4..3c91ff652b 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -150,7 +150,7 @@ static void bochs_crtc_atomic_flush(struct drm_crtc *crtc,
/* These provide the minimum set of functions required to handle a CRTC */
static const struct drm_crtc_funcs bochs_crtc_funcs = {
- .set_config = drm_crtc_helper_set_config,
+ .set_config = drm_atomic_helper_set_config,
.destroy = drm_crtc_cleanup,
.page_flip = bochs_crtc_page_flip,
.reset = drm_atomic_helper_crtc_reset,
--
2.9.3
^ permalink raw reply related
* [PATCH v2 05/15] drm/bochs: atomic: switch planes to atomic, wire up helpers.
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Conversion to atomic modesetting, step three.
Wire up atomic helpers. Switch planes to atomic.
We are late to the party, the transitional helpers are gone,
so this can't be splitted into smaller steps any more.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_fbdev.c | 3 ++
drivers/gpu/drm/bochs/bochs_kms.c | 70 +++++++++++++++++++++++++++++++++++--
2 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
index dd3c7df267..d9f3d42999 100644
--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
+++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
@@ -6,6 +6,7 @@
*/
#include "bochs.h"
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
/* ---------------------------------------------------------------------- */
@@ -149,6 +150,8 @@ bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
const struct drm_mode_config_funcs bochs_mode_funcs = {
.fb_create = bochs_gem_fb_create,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
};
int bochs_fbdev_init(struct bochs_device *bochs)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 56fd7be933..570f761ec4 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -6,7 +6,9 @@
*/
#include "bochs.h"
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic_uapi.h>
static int defx = 1024;
static int defy = 768;
@@ -113,7 +115,7 @@ static int bochs_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *old_fb = crtc->primary->fb;
unsigned long irqflags;
- crtc->primary->fb = fb;
+ drm_atomic_set_fb_for_plane(crtc->primary->state, fb);
bochs_crtc_mode_set_base(crtc, 0, 0, old_fb);
if (event) {
spin_lock_irqsave(&bochs->dev->event_lock, irqflags);
@@ -151,6 +153,9 @@ static const struct drm_crtc_funcs bochs_crtc_funcs = {
.set_config = drm_crtc_helper_set_config,
.destroy = drm_crtc_cleanup,
.page_flip = bochs_crtc_page_flip,
+ .reset = drm_atomic_helper_crtc_reset,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
};
static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
@@ -169,6 +174,59 @@ static const uint32_t bochs_formats[] = {
DRM_FORMAT_BGRX8888,
};
+static void bochs_plane_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct bochs_device *bochs = plane->dev->dev_private;
+ struct bochs_bo *bo;
+
+ if (!plane->state->fb)
+ return;
+ bo = gem_to_bochs_bo(plane->state->fb->obj[0]);
+ bochs_hw_setbase(bochs,
+ plane->state->crtc_x,
+ plane->state->crtc_y,
+ bo->bo.offset);
+ bochs_hw_setformat(bochs, plane->state->fb->format);
+}
+
+static int bochs_plane_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
+{
+ struct bochs_bo *bo;
+
+ if (!new_state->fb)
+ return 0;
+ bo = gem_to_bochs_bo(new_state->fb->obj[0]);
+ return bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+}
+
+static void bochs_plane_cleanup_fb(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ struct bochs_bo *bo;
+
+ if (!old_state->fb)
+ return;
+ bo = gem_to_bochs_bo(old_state->fb->obj[0]);
+ bochs_bo_unpin(bo);
+}
+
+static const struct drm_plane_helper_funcs bochs_plane_helper_funcs = {
+ .atomic_update = bochs_plane_atomic_update,
+ .prepare_fb = bochs_plane_prepare_fb,
+ .cleanup_fb = bochs_plane_cleanup_fb,
+};
+
+static const struct drm_plane_funcs bochs_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_primary_helper_destroy,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
static struct drm_plane *bochs_primary_plane(struct drm_device *dev)
{
struct drm_plane *primary;
@@ -181,16 +239,17 @@ static struct drm_plane *bochs_primary_plane(struct drm_device *dev)
}
ret = drm_universal_plane_init(dev, primary, 0,
- &drm_primary_helper_funcs,
+ &bochs_plane_funcs,
bochs_formats,
ARRAY_SIZE(bochs_formats),
NULL,
DRM_PLANE_TYPE_PRIMARY, NULL);
if (ret) {
kfree(primary);
- primary = NULL;
+ return NULL;
}
+ drm_plane_helper_add(primary, &bochs_plane_helper_funcs);
return primary;
}
@@ -275,6 +334,9 @@ static const struct drm_connector_funcs bochs_connector_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static void bochs_connector_init(struct drm_device *dev)
@@ -318,6 +380,8 @@ int bochs_kms_init(struct bochs_device *bochs)
drm_connector_attach_encoder(&bochs->connector,
&bochs->encoder);
+ drm_mode_config_reset(bochs->dev);
+
return 0;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 04/15] drm/bochs: atomic: add mode_set_nofb callback.
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Conversion to atomic modesetting, step two.
Add mode_set_nofb crtc helper callback.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_kms.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 2cbd406b1f..56fd7be933 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -86,6 +86,14 @@ static int bochs_crtc_mode_set(struct drm_crtc *crtc,
return 0;
}
+static void bochs_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+ struct bochs_device *bochs =
+ container_of(crtc, struct bochs_device, crtc);
+
+ bochs_hw_setmode(bochs, &crtc->mode);
+}
+
static void bochs_crtc_prepare(struct drm_crtc *crtc)
{
}
@@ -149,6 +157,7 @@ static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
.dpms = bochs_crtc_dpms,
.mode_set = bochs_crtc_mode_set,
.mode_set_base = bochs_crtc_mode_set_base,
+ .mode_set_nofb = bochs_crtc_mode_set_nofb,
.prepare = bochs_crtc_prepare,
.commit = bochs_crtc_commit,
.atomic_enable = bochs_crtc_atomic_enable,
--
2.9.3
^ permalink raw reply related
* [PATCH v2 03/15] drm/bochs: atomic: add atomic_flush+atomic_enable callbacks.
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Conversion to atomic modesetting, step one.
Add atomic crtc helper callbacks.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
drivers/gpu/drm/bochs/bochs_kms.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index f7e6d1a9b3..2cbd406b1f 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -115,6 +115,29 @@ static int bochs_crtc_page_flip(struct drm_crtc *crtc,
return 0;
}
+static void bochs_crtc_atomic_enable(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state)
+{
+}
+
+static void bochs_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_pending_vblank_event *event;
+
+ if (crtc->state && crtc->state->event) {
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev->event_lock, irqflags);
+ event = crtc->state->event;
+ crtc->state->event = NULL;
+ drm_crtc_send_vblank_event(crtc, event);
+ spin_unlock_irqrestore(&dev->event_lock, irqflags);
+ }
+}
+
+
/* These provide the minimum set of functions required to handle a CRTC */
static const struct drm_crtc_funcs bochs_crtc_funcs = {
.set_config = drm_crtc_helper_set_config,
@@ -128,6 +151,8 @@ static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
.mode_set_base = bochs_crtc_mode_set_base,
.prepare = bochs_crtc_prepare,
.commit = bochs_crtc_commit,
+ .atomic_enable = bochs_crtc_atomic_enable,
+ .atomic_flush = bochs_crtc_atomic_flush,
};
static const uint32_t bochs_formats[] = {
--
2.9.3
^ permalink raw reply related
* [PATCH v2 02/15] drm/bochs: split bochs_hw_setmode
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Create a separate bochs_hw_setformat function to configure
the framebuffer format (actually just the byteorder).
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs.h | 5 +++--
drivers/gpu/drm/bochs/bochs_hw.c | 19 ++++++++++++-------
drivers/gpu/drm/bochs/bochs_kms.c | 3 ++-
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h
index fb38c8b857..4dc1b6384e 100644
--- a/drivers/gpu/drm/bochs/bochs.h
+++ b/drivers/gpu/drm/bochs/bochs.h
@@ -121,8 +121,9 @@ int bochs_hw_init(struct drm_device *dev);
void bochs_hw_fini(struct drm_device *dev);
void bochs_hw_setmode(struct bochs_device *bochs,
- struct drm_display_mode *mode,
- const struct drm_format_info *format);
+ struct drm_display_mode *mode);
+void bochs_hw_setformat(struct bochs_device *bochs,
+ const struct drm_format_info *format);
void bochs_hw_setbase(struct bochs_device *bochs,
int x, int y, u64 addr);
int bochs_hw_load_edid(struct bochs_device *bochs);
diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c
index d0b4e1cee8..3e04b2f0ec 100644
--- a/drivers/gpu/drm/bochs/bochs_hw.c
+++ b/drivers/gpu/drm/bochs/bochs_hw.c
@@ -204,8 +204,7 @@ void bochs_hw_fini(struct drm_device *dev)
}
void bochs_hw_setmode(struct bochs_device *bochs,
- struct drm_display_mode *mode,
- const struct drm_format_info *format)
+ struct drm_display_mode *mode)
{
bochs->xres = mode->hdisplay;
bochs->yres = mode->vdisplay;
@@ -213,12 +212,8 @@ void bochs_hw_setmode(struct bochs_device *bochs,
bochs->stride = mode->hdisplay * (bochs->bpp / 8);
bochs->yres_virtual = bochs->fb_size / bochs->stride;
- DRM_DEBUG_DRIVER("%dx%d @ %d bpp, format %c%c%c%c, vy %d\n",
+ DRM_DEBUG_DRIVER("%dx%d @ %d bpp, vy %d\n",
bochs->xres, bochs->yres, bochs->bpp,
- (format->format >> 0) & 0xff,
- (format->format >> 8) & 0xff,
- (format->format >> 16) & 0xff,
- (format->format >> 24) & 0xff,
bochs->yres_virtual);
bochs_vga_writeb(bochs, 0x3c0, 0x20); /* unblank */
@@ -236,6 +231,16 @@ void bochs_hw_setmode(struct bochs_device *bochs,
bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
+}
+
+void bochs_hw_setformat(struct bochs_device *bochs,
+ const struct drm_format_info *format)
+{
+ DRM_DEBUG_DRIVER("format %c%c%c%c\n",
+ (format->format >> 0) & 0xff,
+ (format->format >> 8) & 0xff,
+ (format->format >> 16) & 0xff,
+ (format->format >> 24) & 0xff);
switch (format->format) {
case DRM_FORMAT_XRGB8888:
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index c8ce54498d..f7e6d1a9b3 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -80,7 +80,8 @@ static int bochs_crtc_mode_set(struct drm_crtc *crtc,
if (WARN_ON(crtc->primary->fb == NULL))
return -EINVAL;
- bochs_hw_setmode(bochs, mode, crtc->primary->fb->format);
+ bochs_hw_setmode(bochs, mode);
+ bochs_hw_setformat(bochs, crtc->primary->fb->format);
bochs_crtc_mode_set_base(crtc, x, y, old_fb);
return 0;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v2 01/15] drm/bochs: encoder cleanup
From: Gerd Hoffmann @ 2019-01-08 11:25 UTC (permalink / raw)
To: dri-devel, David Airlie
Cc: andr2000, David Airlie, open list,
open list:DRM DRIVER FOR BOCHS VIRTUAL GPU
In-Reply-To: <20190108112519.27473-1-kraxel@redhat.com>
Most unused callbacks can be NULL pointers these days.
Drop a bunch of empty encoder callbacks.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
---
drivers/gpu/drm/bochs/bochs_kms.c | 26 --------------------------
1 file changed, 26 deletions(-)
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index f87c284dd9..c8ce54498d 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -170,31 +170,6 @@ static void bochs_crtc_init(struct drm_device *dev)
drm_crtc_helper_add(crtc, &bochs_helper_funcs);
}
-static void bochs_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
-}
-
-static void bochs_encoder_dpms(struct drm_encoder *encoder, int state)
-{
-}
-
-static void bochs_encoder_prepare(struct drm_encoder *encoder)
-{
-}
-
-static void bochs_encoder_commit(struct drm_encoder *encoder)
-{
-}
-
-static const struct drm_encoder_helper_funcs bochs_encoder_helper_funcs = {
- .dpms = bochs_encoder_dpms,
- .mode_set = bochs_encoder_mode_set,
- .prepare = bochs_encoder_prepare,
- .commit = bochs_encoder_commit,
-};
-
static const struct drm_encoder_funcs bochs_encoder_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
@@ -207,7 +182,6 @@ static void bochs_encoder_init(struct drm_device *dev)
encoder->possible_crtcs = 0x1;
drm_encoder_init(dev, encoder, &bochs_encoder_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
- drm_encoder_helper_add(encoder, &bochs_encoder_helper_funcs);
}
--
2.9.3
^ permalink raw reply related
* Re: [PATCH] vhost/vsock: fix vhost vsock cid hashing inconsistent
From: Stefan Hajnoczi @ 2019-01-08 11:24 UTC (permalink / raw)
To: Zha Bin
Cc: kvm, mst, netdev, linux-kernel, virtualization, stefanha,
kata-dev, gerry
In-Reply-To: <20190108080703.70050-1-zhabin@linux.alibaba.com>
[-- Attachment #1.1: Type: text/plain, Size: 1681 bytes --]
On Tue, Jan 08, 2019 at 04:07:03PM +0800, Zha Bin wrote:
> The vsock core only supports 32bit CID, but the Virtio-vsock spec define
> CID (dst_cid and src_cid) as u64 and the upper 32bits is reserved as
> zero. This inconsistency causes one bug in vhost vsock driver. The
> scenarios is:
>
> 0. A hash table (vhost_vsock_hash) is used to map an CID to a vsock
> object. And hash_min() is used to compute the hash key. hash_min() is
> defined as:
> (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits)).
> That means the hash algorithm has dependency on the size of macro
> argument 'val'.
> 0. In function vhost_vsock_set_cid(), a 64bit CID is passed to
> hash_min() to compute the hash key when inserting a vsock object into
> the hash table.
> 0. In function vhost_vsock_get(), a 32bit CID is passed to hash_min()
> to compute the hash key when looking up a vsock for an CID.
>
> Because the different size of the CID, hash_min() returns different hash
> key, thus fails to look up the vsock object for an CID.
>
> To fix this bug, we keep CID as u64 in the IOCTLs and virtio message
> headers, but explicitly convert u64 to u32 when deal with the hash table
> and vsock core.
>
> Fixes: 834e772c8db0 ("vhost/vsock: fix use-after-free in network stack callers")
> Link: https://github.com/stefanha/virtio/blob/vsock/trunk/content.tex
> Signed-off-by: Zha Bin <zhabin@linux.alibaba.com>
> Reviewed-by: Liu Jiang <gerry@linux.alibaba.com>
> ---
> drivers/vhost/vsock.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Thanks for tracking this down!
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH] drm/virtio: Drop deprecated load/unload initialization
From: Gerd Hoffmann @ 2019-01-08 10:43 UTC (permalink / raw)
To: Ezequiel Garcia; +Cc: David Airlie, Daniel Vetter, dri-devel, virtualization
In-Reply-To: <20190103161600.19556-1-ezequiel@collabora.com>
On Thu, Jan 03, 2019 at 01:16:00PM -0300, Ezequiel Garcia wrote:
> Move the code around so the driver is probed the bus
> .probe and removed from the bus .remove callbacks.
> This commit is just a cleanup and shouldn't affect
> functionality.
Doesn't apply cleanly to drm-misc-next, and git can't find the parent
sha (for 3way merge) either.
Can you rebase and resend?
thanks,
Gerd
^ permalink raw reply
* Re: [PATCH] drm/virtio: Remove incorrect kfree()
From: Gerd Hoffmann @ 2019-01-08 10:40 UTC (permalink / raw)
To: Ezequiel Garcia; +Cc: David Airlie, Daniel Vetter, dri-devel, virtualization
In-Reply-To: <20190102175507.4653-1-ezequiel@collabora.com>
On Wed, Jan 02, 2019 at 02:55:06PM -0300, Ezequiel Garcia wrote:
> The virtio_gpu_output is a member of struct virtio_gpu_device
> and is not a dynamically-allocated chunk, so it's wrong to kfree() it.
> Removing it fixes a memory corruption BUG() that can be triggered
> when the virtio-gpu driver is removed.
>
> Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
Both patches are queued up.
thanks,
Gerd
^ permalink raw reply
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