Message ID | 20221114080752.1900699-1-clg@kaod.org |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2027745wru; Mon, 14 Nov 2022 00:14:56 -0800 (PST) X-Google-Smtp-Source: AA0mqf7/gTq0vTb5CZuiWUW79tyqqbuMEw4iBzwcKPv5lLWShz/a6fCUsHDyei57Slnx1FdYFk18 X-Received: by 2002:a17:907:2a11:b0:78d:1cc8:9fa0 with SMTP id fd17-20020a1709072a1100b0078d1cc89fa0mr9672594ejc.666.1668413695988; Mon, 14 Nov 2022 00:14:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668413695; cv=none; d=google.com; s=arc-20160816; b=af97FkkkStce6N8SHsA30m1Ni7s5brj7eUx6KpJODwxNuZ/bvcxVOwJs98xlW6zi19 G0JOmNP5b7M8yOOcLwS56nt293c8KWLTIO3ilhhcPCdjU6QYxCgH70b0SqvRFQxaPX/C 58I5+tnp+eG1RaNkV1FcMZyKvnbecMz3Ji13gWod1DvYsQB1Cej6IjD9cRBtw9XkDeyC WfKE8TJahzDIsOJMXDObavF/F7nI6Ob8QxMlYjNDPt0lBxxjCMga4GxMr2spQtDGKBhW ffHBik8BTq94APvfNxhCADj1jgb/ssI2+46Cjj4+Y5WsH1Dd8Q0vm8uZwZRriOsA8zs8 JNsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=ih9i0pzbLpUUh8TQWI7r6H41Ycf6oeB+IyHOEhbI6V8=; b=Jnyf6heU+jpqU2VjV5uT9kGDY8JV9PZMIY5Yt49cdxbCBtLmM6C72vzsVCMv4LsYP3 66IcD644YR9tltz/0y0jh5JV2O//xc9kvriiDTwtRKyG1r3XY/ZwICbk0OsHLvPHCyf9 fBQt8i4DZ9OsMAXMLV0OFy7IJlw4elldJpEyocnjQp9iPRCcsI68TCnBuOEy+toeRq3J BqH0zAmC3Y1PYA0VjvH4s8g6uaYI+SrKP5NsQHMlLvSoD9RJuPtB5cWyGhlk1B6kXsAj RqndYW/mwSLar/6sGN4lRCkAFcYWGBn7gTm2sjobsQ2uX4UqGU26P9hT1/Q2Fx25cyp3 yP6A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id js6-20020a17090797c600b0078dffe01cbesi9368412ejc.4.2022.11.14.00.14.32; Mon, 14 Nov 2022 00:14:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236160AbiKNIIH (ORCPT <rfc822;winker.wchi@gmail.com> + 99 others); Mon, 14 Nov 2022 03:08:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235540AbiKNIIF (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 14 Nov 2022 03:08:05 -0500 Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B30B719C08 for <linux-kernel@vger.kernel.org>; Mon, 14 Nov 2022 00:08:04 -0800 (PST) Received: from gandalf.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by gandalf.ozlabs.org (Postfix) with ESMTP id 4N9hkm3Vtjz4xZ3; Mon, 14 Nov 2022 19:08:00 +1100 (AEDT) Received: from authenticated.ozlabs.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.ozlabs.org (Postfix) with ESMTPSA id 4N9hkk1Yjdz4xYV; Mon, 14 Nov 2022 19:07:57 +1100 (AEDT) From: =?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@kaod.org> To: Amit Shah <amit@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, =?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@kaod.org> Subject: [PATCH] virtio_console: Use an atomic to allocate virtual console numbers Date: Mon, 14 Nov 2022 09:07:52 +0100 Message-Id: <20221114080752.1900699-1-clg@kaod.org> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_MED,SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749458559575713456?= X-GMAIL-MSGID: =?utf-8?q?1749458559575713456?= |
Series |
virtio_console: Use an atomic to allocate virtual console numbers
|
|
Commit Message
Cédric Le Goater
Nov. 14, 2022, 8:07 a.m. UTC
When a virtio console port is initialized, it is registered as an hvc
console using a virtual console number. If a KVM guest is started with
multiple virtio console devices, the same vtermno (or virtual console
number) can be used to allocate different hvc consoles, which leads to
various communication problems later on.
This is also reported in debugfs :
# grep vtermno /sys/kernel/debug/virtio-ports/*
/sys/kernel/debug/virtio-ports/vport1p1:console_vtermno: 1
/sys/kernel/debug/virtio-ports/vport2p1:console_vtermno: 1
/sys/kernel/debug/virtio-ports/vport3p1:console_vtermno: 2
/sys/kernel/debug/virtio-ports/vport4p1:console_vtermno: 3
Fix the issue with an atomic variable and start the first console
number at 1 as it is today.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
---
drivers/char/virtio_console.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
Comments
On Mon, Nov 14, 2022 at 09:07:52AM +0100, Cédric Le Goater wrote: > When a virtio console port is initialized, it is registered as an hvc > console using a virtual console number. If a KVM guest is started with > multiple virtio console devices, the same vtermno (or virtual console > number) can be used to allocate different hvc consoles, which leads to > various communication problems later on. > > This is also reported in debugfs : > > # grep vtermno /sys/kernel/debug/virtio-ports/* > /sys/kernel/debug/virtio-ports/vport1p1:console_vtermno: 1 > /sys/kernel/debug/virtio-ports/vport2p1:console_vtermno: 1 > /sys/kernel/debug/virtio-ports/vport3p1:console_vtermno: 2 > /sys/kernel/debug/virtio-ports/vport4p1:console_vtermno: 3 > > Fix the issue with an atomic variable and start the first console > number at 1 as it is today. > > Signed-off-by: Cédric Le Goater <clg@kaod.org> > --- > drivers/char/virtio_console.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c > index 9fa3c76a267f..253574f41e57 100644 > --- a/drivers/char/virtio_console.c > +++ b/drivers/char/virtio_console.c > @@ -58,12 +58,13 @@ struct ports_driver_data { > * We also just assume the first console being initialised was > * the first one that got used as the initial console. > */ > - unsigned int next_vtermno; > + atomic_t next_vtermno; > > /* All the console devices handled by this driver */ > struct list_head consoles; > }; > -static struct ports_driver_data pdrvdata = { .next_vtermno = 1}; > + > +static struct ports_driver_data pdrvdata = { .next_vtermno = ATOMIC_INIT(0) }; > > static DEFINE_SPINLOCK(pdrvdata_lock); > static DECLARE_COMPLETION(early_console_added); > @@ -1244,7 +1245,7 @@ static int init_port_console(struct port *port) > * pointers. The final argument is the output buffer size: we > * can do any size, so we put PAGE_SIZE here. > */ > - port->cons.vtermno = pdrvdata.next_vtermno; > + port->cons.vtermno = atomic_inc_return(&pdrvdata.next_vtermno); Why not use a normal ida/idr structure here? And why is this never decremented? and finally, why not use the value that created the "vportN" number instead? thanks, greg k-h
On 11/14/22 09:57, Greg Kroah-Hartman wrote: > On Mon, Nov 14, 2022 at 09:07:52AM +0100, Cédric Le Goater wrote: >> When a virtio console port is initialized, it is registered as an hvc >> console using a virtual console number. If a KVM guest is started with >> multiple virtio console devices, the same vtermno (or virtual console >> number) can be used to allocate different hvc consoles, which leads to >> various communication problems later on. >> >> This is also reported in debugfs : >> >> # grep vtermno /sys/kernel/debug/virtio-ports/* >> /sys/kernel/debug/virtio-ports/vport1p1:console_vtermno: 1 >> /sys/kernel/debug/virtio-ports/vport2p1:console_vtermno: 1 >> /sys/kernel/debug/virtio-ports/vport3p1:console_vtermno: 2 >> /sys/kernel/debug/virtio-ports/vport4p1:console_vtermno: 3 >> >> Fix the issue with an atomic variable and start the first console >> number at 1 as it is today. >> >> Signed-off-by: Cédric Le Goater <clg@kaod.org> >> --- >> drivers/char/virtio_console.c | 8 ++++---- >> 1 file changed, 4 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c >> index 9fa3c76a267f..253574f41e57 100644 >> --- a/drivers/char/virtio_console.c >> +++ b/drivers/char/virtio_console.c >> @@ -58,12 +58,13 @@ struct ports_driver_data { >> * We also just assume the first console being initialised was >> * the first one that got used as the initial console. >> */ >> - unsigned int next_vtermno; >> + atomic_t next_vtermno; >> >> /* All the console devices handled by this driver */ >> struct list_head consoles; >> }; >> -static struct ports_driver_data pdrvdata = { .next_vtermno = 1}; >> + >> +static struct ports_driver_data pdrvdata = { .next_vtermno = ATOMIC_INIT(0) }; >> >> static DEFINE_SPINLOCK(pdrvdata_lock); >> static DECLARE_COMPLETION(early_console_added); >> @@ -1244,7 +1245,7 @@ static int init_port_console(struct port *port) >> * pointers. The final argument is the output buffer size: we >> * can do any size, so we put PAGE_SIZE here. >> */ >> - port->cons.vtermno = pdrvdata.next_vtermno; >> + port->cons.vtermno = atomic_inc_return(&pdrvdata.next_vtermno); > > Why not use a normal ida/idr structure here? yes that works. > And why is this never decremented? The driver would then need to track the id allocation ... > and finally, why not use the value that created the "vportN" number > instead? yes. we could also encode the tuple (vdev->index, port) using a bitmask, possibly using 'max_nr_ports' to reduce the port width. VIRTCONS_MAX_PORTS seems a bit big for this device and QEMU sets the #ports to 31. An ida might be simpler. One drawback is that an id can be reused for a different device/port tuple in case of an (unlikely) unplug/plug sequence. Thanks, C. > > thanks, > > greg k-h
On Mon, Nov 14, 2022 at 05:03:40PM +0100, Cédric Le Goater wrote: > On 11/14/22 09:57, Greg Kroah-Hartman wrote: > > On Mon, Nov 14, 2022 at 09:07:52AM +0100, Cédric Le Goater wrote: > > > When a virtio console port is initialized, it is registered as an hvc > > > console using a virtual console number. If a KVM guest is started with > > > multiple virtio console devices, the same vtermno (or virtual console > > > number) can be used to allocate different hvc consoles, which leads to > > > various communication problems later on. > > > > > > This is also reported in debugfs : > > > > > > # grep vtermno /sys/kernel/debug/virtio-ports/* > > > /sys/kernel/debug/virtio-ports/vport1p1:console_vtermno: 1 > > > /sys/kernel/debug/virtio-ports/vport2p1:console_vtermno: 1 > > > /sys/kernel/debug/virtio-ports/vport3p1:console_vtermno: 2 > > > /sys/kernel/debug/virtio-ports/vport4p1:console_vtermno: 3 > > > > > > Fix the issue with an atomic variable and start the first console > > > number at 1 as it is today. > > > > > > Signed-off-by: Cédric Le Goater <clg@kaod.org> > > > --- > > > drivers/char/virtio_console.c | 8 ++++---- > > > 1 file changed, 4 insertions(+), 4 deletions(-) > > > > > > diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c > > > index 9fa3c76a267f..253574f41e57 100644 > > > --- a/drivers/char/virtio_console.c > > > +++ b/drivers/char/virtio_console.c > > > @@ -58,12 +58,13 @@ struct ports_driver_data { > > > * We also just assume the first console being initialised was > > > * the first one that got used as the initial console. > > > */ > > > - unsigned int next_vtermno; > > > + atomic_t next_vtermno; > > > /* All the console devices handled by this driver */ > > > struct list_head consoles; > > > }; > > > -static struct ports_driver_data pdrvdata = { .next_vtermno = 1}; > > > + > > > +static struct ports_driver_data pdrvdata = { .next_vtermno = ATOMIC_INIT(0) }; > > > static DEFINE_SPINLOCK(pdrvdata_lock); > > > static DECLARE_COMPLETION(early_console_added); > > > @@ -1244,7 +1245,7 @@ static int init_port_console(struct port *port) > > > * pointers. The final argument is the output buffer size: we > > > * can do any size, so we put PAGE_SIZE here. > > > */ > > > - port->cons.vtermno = pdrvdata.next_vtermno; > > > + port->cons.vtermno = atomic_inc_return(&pdrvdata.next_vtermno); > > > > Why not use a normal ida/idr structure here? > > yes that works. > > > And why is this never decremented? > > The driver would then need to track the id allocation ... That's what an ida/idr does. > > and finally, why not use the value that created the "vportN" number > > instead? > > yes. we could also encode the tuple (vdev->index, port) using a bitmask, No need for that, you already have a unique number in the name above, why not use that? > possibly using 'max_nr_ports' to reduce the port width. Why is that an issue? Maybe I am confused as to what this magic "vtermno" is here. Who uses it and why is the vportN number not sufficient? > VIRTCONS_MAX_PORTS > seems a bit big for this device and QEMU sets the #ports to 31. > > An ida might be simpler. One drawback is that an id can be reused for a > different device/port tuple in case of an (unlikely) unplug/plug sequence. What's wrong with that? We do not have persistent device names from within the kernel. thanks, greg k-h
On 11/14/22 17:18, Greg Kroah-Hartman wrote: > On Mon, Nov 14, 2022 at 05:03:40PM +0100, Cédric Le Goater wrote: >> On 11/14/22 09:57, Greg Kroah-Hartman wrote: >>> On Mon, Nov 14, 2022 at 09:07:52AM +0100, Cédric Le Goater wrote: >>>> When a virtio console port is initialized, it is registered as an hvc >>>> console using a virtual console number. If a KVM guest is started with >>>> multiple virtio console devices, the same vtermno (or virtual console >>>> number) can be used to allocate different hvc consoles, which leads to >>>> various communication problems later on. >>>> >>>> This is also reported in debugfs : >>>> >>>> # grep vtermno /sys/kernel/debug/virtio-ports/* >>>> /sys/kernel/debug/virtio-ports/vport1p1:console_vtermno: 1 >>>> /sys/kernel/debug/virtio-ports/vport2p1:console_vtermno: 1 >>>> /sys/kernel/debug/virtio-ports/vport3p1:console_vtermno: 2 >>>> /sys/kernel/debug/virtio-ports/vport4p1:console_vtermno: 3 >>>> >>>> Fix the issue with an atomic variable and start the first console >>>> number at 1 as it is today. >>>> >>>> Signed-off-by: Cédric Le Goater <clg@kaod.org> >>>> --- >>>> drivers/char/virtio_console.c | 8 ++++---- >>>> 1 file changed, 4 insertions(+), 4 deletions(-) >>>> >>>> diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c >>>> index 9fa3c76a267f..253574f41e57 100644 >>>> --- a/drivers/char/virtio_console.c >>>> +++ b/drivers/char/virtio_console.c >>>> @@ -58,12 +58,13 @@ struct ports_driver_data { >>>> * We also just assume the first console being initialised was >>>> * the first one that got used as the initial console. >>>> */ >>>> - unsigned int next_vtermno; >>>> + atomic_t next_vtermno; >>>> /* All the console devices handled by this driver */ >>>> struct list_head consoles; >>>> }; >>>> -static struct ports_driver_data pdrvdata = { .next_vtermno = 1}; >>>> + >>>> +static struct ports_driver_data pdrvdata = { .next_vtermno = ATOMIC_INIT(0) }; >>>> static DEFINE_SPINLOCK(pdrvdata_lock); >>>> static DECLARE_COMPLETION(early_console_added); >>>> @@ -1244,7 +1245,7 @@ static int init_port_console(struct port *port) >>>> * pointers. The final argument is the output buffer size: we >>>> * can do any size, so we put PAGE_SIZE here. >>>> */ >>>> - port->cons.vtermno = pdrvdata.next_vtermno; >>>> + port->cons.vtermno = atomic_inc_return(&pdrvdata.next_vtermno); >>> >>> Why not use a normal ida/idr structure here? >> >> yes that works. >> >>> And why is this never decremented? >> >> The driver would then need to track the id allocation ... > > That's what an ida/idr does. > >>> and finally, why not use the value that created the "vportN" number >>> instead? >> >> yes. we could also encode the tuple (vdev->index, port) using a bitmask, > > No need for that, you already have a unique number in the name above, > why not use that? > >> possibly using 'max_nr_ports' to reduce the port width. > > Why is that an issue? Maybe I am confused as to what this magic > "vtermno" is here. Who uses it and why is the vportN number not > sufficient? A virtio console device can have multiple ports each being a /dev/hvcX exposed in the guest OS. The "vportN" prefix identifies the virtio device : # grep vtermno /sys/kernel/debug/virtio-ports/* /sys/kernel/debug/virtio-ports/vport1p0:console_vtermno: 2 /sys/kernel/debug/virtio-ports/vport1p1:console_vtermno: 3 /sys/kernel/debug/virtio-ports/vport1p2:console_vtermno: 4 /sys/kernel/debug/virtio-ports/vport1p3:console_vtermno: 5 /sys/kernel/debug/virtio-ports/vport2p0:console_vtermno: 1 /sys/kernel/debug/virtio-ports/vport2p1:console_vtermno: 6 /sys/kernel/debug/virtio-ports/vport2p2:console_vtermno: 7 /sys/kernel/debug/virtio-ports/vport2p3:console_vtermno: 8 and "pX" the port within in the device. The naming is a bit confusing. >> VIRTCONS_MAX_PORTS >> seems a bit big for this device and QEMU sets the #ports to 31. >> >> An ida might be simpler. One drawback is that an id can be reused for a >> different device/port tuple in case of an (unlikely) unplug/plug sequence. > > What's wrong with that? We do not have persistent device names from > within the kernel. Let's go with the ida then. Thanks, C.
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 9fa3c76a267f..253574f41e57 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -58,12 +58,13 @@ struct ports_driver_data { * We also just assume the first console being initialised was * the first one that got used as the initial console. */ - unsigned int next_vtermno; + atomic_t next_vtermno; /* All the console devices handled by this driver */ struct list_head consoles; }; -static struct ports_driver_data pdrvdata = { .next_vtermno = 1}; + +static struct ports_driver_data pdrvdata = { .next_vtermno = ATOMIC_INIT(0) }; static DEFINE_SPINLOCK(pdrvdata_lock); static DECLARE_COMPLETION(early_console_added); @@ -1244,7 +1245,7 @@ static int init_port_console(struct port *port) * pointers. The final argument is the output buffer size: we * can do any size, so we put PAGE_SIZE here. */ - port->cons.vtermno = pdrvdata.next_vtermno; + port->cons.vtermno = atomic_inc_return(&pdrvdata.next_vtermno); port->cons.hvc = hvc_alloc(port->cons.vtermno, 0, &hv_ops, PAGE_SIZE); if (IS_ERR(port->cons.hvc)) { @@ -1255,7 +1256,6 @@ static int init_port_console(struct port *port) return ret; } spin_lock_irq(&pdrvdata_lock); - pdrvdata.next_vtermno++; list_add_tail(&port->cons.list, &pdrvdata.consoles); spin_unlock_irq(&pdrvdata_lock); port->guest_connected = true;