From patchwork Wed May 30 21:27:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 137290 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp5816546lji; Wed, 30 May 2018 14:28:29 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKOfk/VuQ2KPTacNuC+joumYFL+iWvtxZ4bTfjc3tyHWGNXL/R3w8Vqr3JBW4mFCcD6b5ej X-Received: by 2002:a17:902:42a3:: with SMTP id h32-v6mr4430291pld.72.1527715709274; Wed, 30 May 2018 14:28:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527715709; cv=none; d=google.com; s=arc-20160816; b=O3rWpnw9Itj65veRqWxMp4cWw2Z+bwff1vFBk5uXQKCInaBXGswjObSoNLS1IHybLf HInittLch5yo8rYnde/FnVbrcxbOf/1Xzdf44pkoiOBTga+8UsKwIyEXlRstJ1NrtPIv u3+PKqNi7es4iH5P1fH98TSqx8VYYHNdZAyBEnu/vafKL5UB6hi1RkCQVJiTEOCcq82f tF8Ikz5vbPZcu+tEfe1fQqkcndiui7YEQBsHFCkNUxUoLsJUaDliX1ubuNiSrcq5ToUc AV0DGx74FWzLQjnu9wTsP1VWkx20usMknxYH6fhNyM83Mj9MyvxB0L4W+0WlhCd/TBib e84w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=KBVCz/A4/QKu+Ny7CChZ6mXS+SUXRx1oIzPCcCSIges=; b=PhXJiAqLh6ZQwMrMwseec0anZBf6v7K+WTjUwQPiVh52AtKY5tsg++mi54BWFZGSds ukHY1pFXDWN9RtOifogJgByWtaRrRfoBKReSWOg+5GH/tNNkA6evCd0KduNGphXcy5pf qzRkE2cFfgKgflFipkXZCJEySH3jbO4lEQ+sX1ZUEy16gvQIBp02qRU+0bFiRN0fgHsQ FriOV0ODfs48XcT36GUnhAhnqd333KyAvoFxvCRMoUvn1fv846lyIJdqK0ZnHdX3G/5M 8SKbN8IIEyM6y7aL/TKnSd0iZh6BHMVS/axe9hQJVYevmX6/97bX4MwXOMvnY4VROPhu RdIw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=A408m1D6; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 5-v6si36237263plx.517.2018.05.30.14.28.29; Wed, 30 May 2018 14:28:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=A408m1D6; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932563AbeE3V20 (ORCPT + 30 others); Wed, 30 May 2018 17:28:26 -0400 Received: from pb-smtp1.pobox.com ([64.147.108.70]:63592 "EHLO pb-smtp1.pobox.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932382AbeE3V2V (ORCPT ); Wed, 30 May 2018 17:28:21 -0400 Received: from pb-smtp1.pobox.com (unknown [127.0.0.1]) by pb-smtp1.pobox.com (Postfix) with ESMTP id 21F89F2C61; Wed, 30 May 2018 17:28:19 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=sasl; bh=uxqV sKozu7t18hByTPZhHNi4yGc=; b=A408m1D6UZarsb02BnCgK77NChzAjkBfDZRD 2rTTg/TKSsKnY6mBkKa08UR8TKRyDcnBF/6vhmPZr+i0t2IIqvoD/ea9TFbo9hVi LI1cjM9YXbNriCPF3KIXTIVheuii8FnhwKYojIgHpYOh/lqb/4J/i2yg8DC1Ly3b fTShDII= Received: from pb-smtp1.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp1.pobox.com (Postfix) with ESMTP id 1891EF2C5F; Wed, 30 May 2018 17:28:19 -0400 (EDT) Received: from yoda.home (unknown [70.82.104.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp1.pobox.com (Postfix) with ESMTPSA id 9F7CEF2C5E; Wed, 30 May 2018 17:28:18 -0400 (EDT) Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id BBA492DA0513; Wed, 30 May 2018 17:28:17 -0400 (EDT) From: Nicolas Pitre To: Greg Kroah-Hartman Cc: Dave Mielke , Samuel Thibault , linux-kernel@vger.kernel.org Subject: [PATCH 1/5] vt: perform safe console erase only once Date: Wed, 30 May 2018 17:27:41 -0400 Message-Id: <20180530212745.10997-2-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530212745.10997-1-nicolas.pitre@linaro.org> References: <20180530212745.10997-1-nicolas.pitre@linaro.org> X-Pobox-Relay-ID: 5EE000B8-6450-11E8-8397-44CE1968708C-78420484!pb-smtp1.pobox.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit f8df13e0a9 ("tty: Clean console safely") added code to clear both the scrollback buffer and the screen with "\e[3J", then execution falls through into the code to simply clear the screen. This means scr_memsetw() and the console driver update callback is called twice on the whole screen buffer. Let's reorganize the code so the same work is not performed twice. Signed-off-by: Nicolas Pitre --- drivers/tty/vt/vt.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) -- 2.17.0 diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index f97251f39c..1eb1a376a0 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1178,15 +1178,8 @@ static void csi_J(struct vc_data *vc, int vpar) count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; start = (unsigned short *)vc->vc_origin; break; - case 3: /* erase scroll-back buffer (and whole display) */ - scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, - vc->vc_screenbuf_size); - flush_scrollback(vc); - set_origin(vc); - if (con_is_visible(vc)) - update_screen(vc); - /* fall through */ case 2: /* erase whole display */ + case 3: /* (and scrollback buffer later) */ count = vc->vc_cols * vc->vc_rows; start = (unsigned short *)vc->vc_origin; break; @@ -1194,7 +1187,12 @@ static void csi_J(struct vc_data *vc, int vpar) return; } scr_memsetw(start, vc->vc_video_erase_char, 2 * count); - if (con_should_update(vc)) + if (vpar == 3) { + set_origin(vc); + flush_scrollback(vc); + if (con_is_visible(vc)) + update_screen(vc); + } else if (con_should_update(vc)) do_update_region(vc, (unsigned long) start, count); vc->vc_need_wrap = 0; } From patchwork Wed May 30 21:27:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 137293 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp5817276lji; Wed, 30 May 2018 14:29:26 -0700 (PDT) X-Google-Smtp-Source: ADUXVKICe9iZVgFwGbhcbXZ0Zomc5Wys/yZP2JtVxZe06RglZYt9+J1x4c/zLz4/72RsWQ8hiLim X-Received: by 2002:a63:a513:: with SMTP id n19-v6mr3359350pgf.381.1527715766411; Wed, 30 May 2018 14:29:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527715766; cv=none; d=google.com; s=arc-20160816; b=g+TdL8LsSY+2ctPrCt12E65foZMG1bEPHP3oIbUFJ4Jl7GOB6f4rNixwt3dCIVszg8 rgO8QI2vwAN3NSRGueuSYkUn2pBFeOi2NvJaEBfszIWCCu8yHEljI6i5C/09Ei5NCxiQ CU5BLCiHAi9FZ3YIeJyK5jgR63u6M5wDNCb/UFy2khc6VkZwfvqWsHlzQzBL1QiUjALL D4jw9HEoq3qmS1WZv+uAevRCACybcwDu8E1nVdTvDywfGqeMRbSG/7TErZnkU7HMn+Eq n6hTaEbh1QBg5e5OduJXmmyBffycEqZfkdJ1Ob5//HNJJtIpVVh/oS8kos+wpRLMDCBQ oIYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=i+A0O9+r5SI1LieKBSxQtvs/ifWAcG5/ZRVwbrfRWn0=; b=sZsdmogVa20kkz/TSky5OJ3FtG9JtxotkVdQaaIG9oZwYrdTpy3wKzzc9hysOUNC17 46gyYi/z+c6dJO/O4I4wJOwCFaFNc6q4xqpW/LFGXb/B56UO+i6BFjFpoji+Vs+hDUtE Wxdo6RBXPbb+M+zUMbnP2MojzifbBmKYekucKKkepkrPEsjOyvF4ECNw676rk1GhJMrn +wRevdfw5ImYP4IbIb7gU/j2JTqFMBRz5kmjn8asxYk6gaSSJ+/wcrZs8dc8bbn99RaG UqZlWy913shIzhIRwmMuoMjCQawuU036Vq8pgZSsrLnupBkrKRwyL4BpIxgPh1NEzn+n bU2A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=Ckm96ZFO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 142-v6si11054667pga.694.2018.05.30.14.29.26; Wed, 30 May 2018 14:29:26 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=Ckm96ZFO; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932414AbeE3V3Y (ORCPT + 30 others); Wed, 30 May 2018 17:29:24 -0400 Received: from pb-smtp2.pobox.com ([64.147.108.71]:64589 "EHLO pb-smtp2.pobox.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932359AbeE3V2V (ORCPT ); Wed, 30 May 2018 17:28:21 -0400 Received: from pb-smtp2.pobox.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 2B93BF3515; Wed, 30 May 2018 17:28:19 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=sasl; bh=BG5a pSOvxapGTbI20w1zGDhyD84=; b=Ckm96ZFOjn3rtoXlBb+wL8Y0VHR3NqjlucAs WvnpNhAUclqbaxbGc68Blu5dLJMeZoldG6al72qQj69IF4o5q/8LcTdEw8LFRL5E kdPb2eLGJLpADWBLgRIWMVF97dlN5kjMgQO8sOHXsW3NxcFiomZy1J+kZ2JPPgv7 mnD3E1k= Received: from pb-smtp2.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 24046F3514; Wed, 30 May 2018 17:28:19 -0400 (EDT) Received: from yoda.home (unknown [70.82.104.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp2.pobox.com (Postfix) with ESMTPSA id 9AF37F350F; Wed, 30 May 2018 17:28:18 -0400 (EDT) Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id DF2172DA0543; Wed, 30 May 2018 17:28:17 -0400 (EDT) From: Nicolas Pitre To: Greg Kroah-Hartman Cc: Dave Mielke , Samuel Thibault , linux-kernel@vger.kernel.org Subject: [PATCH 2/5] vt: preserve unicode values corresponding to screen characters Date: Wed, 30 May 2018 17:27:42 -0400 Message-Id: <20180530212745.10997-3-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530212745.10997-1-nicolas.pitre@linaro.org> References: <20180530212745.10997-1-nicolas.pitre@linaro.org> X-Pobox-Relay-ID: 5EDD3F72-6450-11E8-B536-67830C78B957-78420484!pb-smtp2.pobox.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The vt code translates UTF-8 strings into glyph index values and stores those glyph values directly in the screen buffer. Because there can only be at most 512 glyphs, it is impossible to represent most unicode characters, in which case a default glyph (often '?') is displayed instead. The original unicode value is then lost. This patch implements the basic screen buffer handling to preserve unicode values alongside corresponding display glyphs. It is not activated by default, meaning that people not relying on that functionality won't get the implied overhead. Signed-off-by: Nicolas Pitre Tested-by: Dave Mielke --- drivers/tty/vt/vt.c | 222 +++++++++++++++++++++++++++++++-- include/linux/console_struct.h | 2 + 2 files changed, 213 insertions(+), 11 deletions(-) -- 2.17.0 diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 1eb1a376a0..3a801a60f4 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -317,6 +317,173 @@ void schedule_console_callback(void) schedule_work(&console_work); } +/* + * Code to manage unicode-based screen buffers + */ + +#ifdef NO_VC_UNI_SCREEN +/* this disables and optimizes related code away at compile time */ +#define get_vc_uniscr(vc) NULL +#else +#define get_vc_uniscr(vc) vc->vc_uni_screen +#endif + +typedef uint32_t char32_t; + +/* + * Our screen buffer is preceded by an array of line pointers so that + * scrolling only implies some pointer shuffling. + */ +struct uni_screen { + char32_t *lines[0]; +}; + +static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows) +{ + struct uni_screen *uniscr; + void *p; + unsigned int memsize, i; + + /* allocate everything in one go */ + memsize = cols * rows * sizeof(char32_t); + memsize += rows * sizeof(char32_t *); + p = kmalloc(memsize, GFP_KERNEL); + if (!p) { + pr_err("unable to allocate unicode screen buffer"); + return NULL; + } + + /* initial line pointers */ + uniscr = p; + p = uniscr->lines + rows; + for (i = 0; i < rows; i++) { + uniscr->lines[i] = p; + p += cols * sizeof(char32_t); + } + return uniscr; +} + +static void vc_uniscr_set(struct vc_data *vc, struct uni_screen *new_uniscr) +{ + kfree(vc->vc_uni_screen); + vc->vc_uni_screen = new_uniscr; +} + +static void vc_uniscr_putc(struct vc_data *vc, char32_t uc) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + if (uniscr) + uniscr->lines[vc->vc_y][vc->vc_x] = uc; +} + +static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + if (uniscr) { + char32_t *ln = uniscr->lines[vc->vc_y]; + unsigned int x = vc->vc_x, cols = vc->vc_cols; + + memmove(&ln[x + nr], &ln[x], (cols - x - nr) * sizeof(*ln)); + memset32(&ln[x], ' ', nr); + } +} + +static void vc_uniscr_delete(struct vc_data *vc, unsigned int nr) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + if (uniscr) { + char32_t *ln = uniscr->lines[vc->vc_y]; + unsigned int x = vc->vc_x, cols = vc->vc_cols; + + memcpy(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln)); + memset32(&ln[cols - nr], ' ', nr); + } +} + +static void vc_uniscr_clear_line(struct vc_data *vc, unsigned int x, + unsigned int nr) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + if (uniscr) { + char32_t *ln = uniscr->lines[vc->vc_y]; + + memset32(&ln[x], ' ', nr); + } +} + +static void vc_uniscr_clear_lines(struct vc_data *vc, unsigned int y, + unsigned int nr) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + if (uniscr) { + unsigned int cols = vc->vc_cols; + + while (nr--) + memset32(uniscr->lines[y++], ' ', cols); + } +} + +static void vc_uniscr_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int nr) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + if (uniscr) { + unsigned int s, d, rescue, clear; + char32_t *save[nr]; + + s = clear = t; + d = t + nr; + rescue = b - nr; + if (dir == SM_UP) { + swap(s, d); + swap(clear, rescue); + } + memcpy(save, uniscr->lines + rescue, nr * sizeof(*save)); + memmove(uniscr->lines + d, uniscr->lines + s, + (b - t - nr) * sizeof(*uniscr->lines)); + memcpy(uniscr->lines + clear, save, nr * sizeof(*save)); + vc_uniscr_clear_lines(vc, clear, nr); + } +} + +static void vc_uniscr_copy_area(struct uni_screen *dst, + unsigned int dst_cols, + unsigned int dst_rows, + struct uni_screen *src, + unsigned int src_cols, + unsigned int src_top_row, + unsigned int src_bot_row) +{ + unsigned int dst_row = 0; + + if (!dst) + return; + + while (src_top_row < src_bot_row) { + char32_t *src_line = src->lines[src_top_row]; + char32_t *dst_line = dst->lines[dst_row]; + + memcpy(dst_line, src_line, src_cols * sizeof(char32_t)); + if (dst_cols - src_cols) + memset32(dst_line + src_cols, ' ', dst_cols - src_cols); + src_top_row++; + dst_row++; + } + while (dst_row < dst_rows) { + char32_t *dst_line = dst->lines[dst_row]; + + memset32(dst_line, ' ', dst_cols); + dst_row++; + } +} + + static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b, enum con_scroll dir, unsigned int nr) { @@ -326,6 +493,7 @@ static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b, nr = b - t - 1; if (b > vc->vc_rows || t >= b || nr < 1) return; + vc_uniscr_scroll(vc, t, b, dir, nr); if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, dir, nr)) return; @@ -533,6 +701,7 @@ static void insert_char(struct vc_data *vc, unsigned int nr) { unsigned short *p = (unsigned short *) vc->vc_pos; + vc_uniscr_insert(vc, nr); scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2); scr_memsetw(p, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; @@ -545,6 +714,7 @@ static void delete_char(struct vc_data *vc, unsigned int nr) { unsigned short *p = (unsigned short *) vc->vc_pos; + vc_uniscr_delete(vc, nr); scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2); scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char, nr * 2); @@ -845,10 +1015,11 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned long end; - unsigned int old_rows, old_row_size; + unsigned int old_rows, old_row_size, first_copied_row; unsigned int new_cols, new_rows, new_row_size, new_screen_size; unsigned int user; unsigned short *newscreen; + struct uni_screen *new_uniscr = NULL; WARN_CONSOLE_UNLOCKED(); @@ -875,6 +1046,14 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, if (!newscreen) return -ENOMEM; + if (get_vc_uniscr(vc)) { + new_uniscr = vc_uniscr_alloc(new_cols, new_rows); + if (!new_uniscr) { + kfree(newscreen); + return -ENOMEM; + } + } + if (vc == sel_cons) clear_selection(); @@ -884,6 +1063,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, err = resize_screen(vc, new_cols, new_rows, user); if (err) { kfree(newscreen); + kfree(new_uniscr); return err; } @@ -904,18 +1084,24 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, * Cursor near the bottom, copy contents from the * bottom of buffer */ - old_origin += (old_rows - new_rows) * old_row_size; + first_copied_row = (old_rows - new_rows); } else { /* * Cursor is in no man's land, copy 1/2 screenful * from the top and bottom of cursor position */ - old_origin += (vc->vc_y - new_rows/2) * old_row_size; + first_copied_row = (vc->vc_y - new_rows/2); } - } - + old_origin += first_copied_row * old_row_size; + } else + first_copied_row = 0; end = old_origin + old_row_size * min(old_rows, new_rows); + vc_uniscr_copy_area(new_uniscr, new_cols, new_rows, + get_vc_uniscr(vc), rlth/2, first_copied_row, + min(old_rows, new_rows)); + vc_uniscr_set(vc, new_uniscr); + update_attr(vc); while (old_origin < end) { @@ -1013,6 +1199,7 @@ struct vc_data *vc_deallocate(unsigned int currcons) vc->vc_sw->con_deinit(vc); put_pid(vc->vt_pid); module_put(vc->vc_sw->owner); + vc_uniscr_set(vc, NULL); kfree(vc->vc_screenbuf); vc_cons[currcons].d = NULL; } @@ -1171,15 +1358,22 @@ static void csi_J(struct vc_data *vc, int vpar) switch (vpar) { case 0: /* erase from cursor to end of display */ + vc_uniscr_clear_line(vc, vc->vc_x, + vc->vc_cols - vc->vc_x); + vc_uniscr_clear_lines(vc, vc->vc_y + 1, + vc->vc_rows - vc->vc_y - 1); count = (vc->vc_scr_end - vc->vc_pos) >> 1; start = (unsigned short *)vc->vc_pos; break; case 1: /* erase from start to cursor */ + vc_uniscr_clear_line(vc, 0, vc->vc_x + 1); + vc_uniscr_clear_lines(vc, 0, vc->vc_y); count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; start = (unsigned short *)vc->vc_origin; break; case 2: /* erase whole display */ case 3: /* (and scrollback buffer later) */ + vc_uniscr_clear_lines(vc, 0, vc->vc_rows); count = vc->vc_cols * vc->vc_rows; start = (unsigned short *)vc->vc_origin; break; @@ -1200,25 +1394,27 @@ static void csi_J(struct vc_data *vc, int vpar) static void csi_K(struct vc_data *vc, int vpar) { unsigned int count; - unsigned short * start; + unsigned short *start = (unsigned short *)vc->vc_pos; + int offset; switch (vpar) { case 0: /* erase from cursor to end of line */ + offset = 0; count = vc->vc_cols - vc->vc_x; - start = (unsigned short *)vc->vc_pos; break; case 1: /* erase from start of line to cursor */ - start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1)); + offset = -vc->vc_x; count = vc->vc_x + 1; break; case 2: /* erase whole line */ - start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1)); + offset = -vc->vc_x; count = vc->vc_cols; break; default: return; } - scr_memsetw(start, vc->vc_video_erase_char, 2 * count); + vc_uniscr_clear_line(vc, vc->vc_x + offset, count); + scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count); vc->vc_need_wrap = 0; if (con_should_update(vc)) do_update_region(vc, (unsigned long) start, count); @@ -1232,6 +1428,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi vpar++; count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar; + vc_uniscr_clear_line(vc, vc->vc_x, count); scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); if (con_should_update(vc)) vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count); @@ -2188,7 +2385,7 @@ static void con_flush(struct vc_data *vc, unsigned long draw_from, /* acquires console_lock */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) { - int c, tc, ok, n = 0, draw_x = -1; + int c, next_c, tc, ok, n = 0, draw_x = -1; unsigned int currcons; unsigned long draw_from = 0, draw_to = 0; struct vc_data *vc; @@ -2382,6 +2579,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co con_flush(vc, draw_from, draw_to, &draw_x); } + next_c = c; while (1) { if (vc->vc_need_wrap || vc->vc_decim) con_flush(vc, draw_from, draw_to, @@ -2392,6 +2590,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co } if (vc->vc_decim) insert_char(vc, 1); + vc_uniscr_putc(vc, next_c); scr_writew(himask ? ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : (vc_attr << 8) + tc, @@ -2412,6 +2611,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ if (tc < 0) tc = ' '; + next_c = ' '; } notify_write(vc, c); diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index c0ec478ea5..2c8d323989 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -19,6 +19,7 @@ struct vt_struct; struct uni_pagedir; +struct uni_screen; #define NPAR 16 @@ -140,6 +141,7 @@ struct vc_data { struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ struct uni_pagedir *vc_uni_pagedir; struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ + struct uni_screen *vc_uni_screen; /* unicode screen content */ bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */ /* additional information is in vt_kern.h */ }; From patchwork Wed May 30 21:27:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 137292 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp5817217lji; Wed, 30 May 2018 14:29:21 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJZ0npWVJgDZWa59DwoL+BNZydEos85peA3kPDivFC1bh6NVnbjyZfLZ4NU5Uz4jXoLoTFd X-Received: by 2002:a17:902:1aa:: with SMTP id b39-v6mr4387590plb.120.1527715761425; Wed, 30 May 2018 14:29:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527715761; cv=none; d=google.com; s=arc-20160816; b=b7alvY1hWM+5WKbL4YrWg4i+pGwtCagjk1lWlT4mkNxbPN6yH2DSCrHhhQnXNmSvM1 IsHLecFBrOQ2D1JjVUHMbq3n9O02uZnhAHmjfghTSoeKr485TLBy8dlr6ipUsj2uwYmE A0tUzxDvrmPK4Qkag33lKbcu+zoaJdxdyl3h+gGjtbe8GOsZB6V3KgQeKlodK1bXM1dp k8s8wpHzScVo32yDVvl7z9nk5FWcQlX1vVZOiwCOe0Gxbu18OH3LukI6l9Csw7atUsB2 mVttx1Vo23LrPgT6j1IZCTmoev8TH9StnpbU96JwBGAQbpPfcUaQcrrnXDFcbdNCYWL4 mB9w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=W+cPxej7NLVm9Ai4/ODMMqqIKupkxZn4+CJyCuIkXDo=; b=nnzaXkI8ByBHMkVLusoCMQsTOGLrtrsV8boci6ILEvZBi1xxdsX/BHPVmarLG0xkzK yBWbe65PH2cH9rKY3qne5cidgDQCyERHgKhazZVf3kq1/OyVynQwVBpso3P2AgIuiERj 2JsE02m3EwBQ05vqAxtd0BeVPS5BA/huJI+KiSfVqfLdlCE5MyS8Zp4dB+DqXosWrCAq s2MbxTeMLYDrASpRBRc9MTrGfJdpjGWlYmPVYOFosXuTQ5z1Zr9/mubq1jVRZfS4MlmA hHXpI4KTNFI9jTM+pclwfOwJs2lVsaTt9gWp3OmkV91+M6C07XJyeWDAl+JeSnF4mGXo tEuQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=I1zImX7T; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 142-v6si11054667pga.694.2018.05.30.14.29.21; Wed, 30 May 2018 14:29:21 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=I1zImX7T; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932621AbeE3V3S (ORCPT + 30 others); Wed, 30 May 2018 17:29:18 -0400 Received: from pb-smtp2.pobox.com ([64.147.108.71]:54855 "EHLO pb-smtp2.pobox.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932402AbeE3V2V (ORCPT ); Wed, 30 May 2018 17:28:21 -0400 Received: from pb-smtp2.pobox.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 52693F3518; Wed, 30 May 2018 17:28:19 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references:mime-version :content-type:content-transfer-encoding; s=sasl; bh=7/XAO+Hax1n3 TNG7LB0OA6bInwI=; b=I1zImX7TG2rRI0XpQJigBSsto7eWCUmEVR+4dHvKbUZb 184OVhcuKUePjttZ358WB0RxKM770ikXDVXxHV3UhGkzEdIm7bCH9lpa1+v8hL/I y1CVRSs9gzfCty+yFB33b3Ybo5AthsqYn3/RK5+A9oa/mgWnZf9783ob5oasUgM= Received: from pb-smtp2.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 47DFFF3516; Wed, 30 May 2018 17:28:19 -0400 (EDT) Received: from yoda.home (unknown [70.82.104.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp2.pobox.com (Postfix) with ESMTPSA id BC293F3510; Wed, 30 May 2018 17:28:18 -0400 (EDT) Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id 0BEE62DA06A7; Wed, 30 May 2018 17:28:18 -0400 (EDT) From: Nicolas Pitre To: Greg Kroah-Hartman Cc: Dave Mielke , Samuel Thibault , linux-kernel@vger.kernel.org Subject: [PATCH 3/5] vt: introduce unicode mode for /dev/vcs Date: Wed, 30 May 2018 17:27:43 -0400 Message-Id: <20180530212745.10997-4-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530212745.10997-1-nicolas.pitre@linaro.org> References: <20180530212745.10997-1-nicolas.pitre@linaro.org> MIME-Version: 1.0 X-Pobox-Relay-ID: 5EF23544-6450-11E8-B718-67830C78B957-78420484!pb-smtp2.pobox.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Now that the core vt code knows how to preserve unicode values for each displayed character, it is then possible to let user space access it via /dev/vcs*. Unicode characters are presented as 32 bit values in native endianity via the /dev/vcsu* devices, mimicking the simple /dev/vcs* devices. Unicode with attributes (similarly to /dev/vcsa*) is not supported at the moment. Data is available only as long as the console is in UTF-8 mode. ENODATA is returned otherwise. This was tested with the latest development version (to become version 5.7) of BRLTTY. Amongst other things, this allows ⠋⠕⠗ ⠞⠓⠊⠎ ⠃⠗⠁⠊⠇⠇⠑⠀⠞⠑⠭⠞⠀to appear directly on braille displays regardless of the console font being used. Signed-off-by: Nicolas Pitre Tested-by: Dave Mielke --- drivers/tty/vt/vc_screen.c | 89 ++++++++++++++++++++++++++++++++------ drivers/tty/vt/vt.c | 61 ++++++++++++++++++++++++++ include/linux/selection.h | 5 +++ 3 files changed, 141 insertions(+), 14 deletions(-) -- 2.17.0 diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index e4a66e1fd0..9c44252e52 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -10,6 +10,12 @@ * Attribute/character pair is in native endianity. * [minor: N+128] * + * /dev/vcsuN: similar to /dev/vcsaN but using 4-byte unicode values + * instead of 1-byte screen glyph values. + * [minor: N+64] + * + * /dev/vcsuaN: same idea as /dev/vcsaN for unicode (not yet implemented). + * * This replaces screendump and part of selection, so that the system * administrator can control access using file system permissions. * @@ -51,6 +57,26 @@ #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE) +/* + * Our minor space: + * + * 0 ... 63 glyph mode without attributes + * 64 ... 127 unicode mode without attributes + * 128 ... 191 glyph mode with attributes + * 192 ... 255 unused (reserved for unicode with attributes) + * + * This relies on MAX_NR_CONSOLES being <= 63, meaning 63 actual consoles + * with minors 0, 64, 128 and 192 being proxies for the foreground console. + */ +#if MAX_NR_CONSOLES > 63 +#warning "/dev/vcs* devices may not accommodate more than 63 consoles" +#endif + +#define console(inode) (iminor(inode) & 63) +#define use_unicode(inode) (iminor(inode) & 64) +#define use_attributes(inode) (iminor(inode) & 128) + + struct vcs_poll_data { struct notifier_block notifier; unsigned int cons_num; @@ -102,7 +128,7 @@ vcs_poll_data_get(struct file *file) poll = kzalloc(sizeof(*poll), GFP_KERNEL); if (!poll) return NULL; - poll->cons_num = iminor(file_inode(file)) & 127; + poll->cons_num = console(file_inode(file)); init_waitqueue_head(&poll->waitq); poll->notifier.notifier_call = vcs_notifier; if (register_vt_notifier(&poll->notifier) != 0) { @@ -140,7 +166,7 @@ vcs_poll_data_get(struct file *file) static struct vc_data* vcs_vc(struct inode *inode, int *viewed) { - unsigned int currcons = iminor(inode) & 127; + unsigned int currcons = console(inode); WARN_CONSOLE_UNLOCKED(); @@ -164,7 +190,6 @@ static int vcs_size(struct inode *inode) { int size; - int minor = iminor(inode); struct vc_data *vc; WARN_CONSOLE_UNLOCKED(); @@ -175,8 +200,12 @@ vcs_size(struct inode *inode) size = vc->vc_rows * vc->vc_cols; - if (minor & 128) + if (use_attributes(inode)) { + if (use_unicode(inode)) + return -EOPNOTSUPP; size = 2*size + HEADER_SIZE; + } else if (use_unicode(inode)) + size *= 4; return size; } @@ -197,12 +226,10 @@ static ssize_t vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file_inode(file); - unsigned int currcons = iminor(inode); struct vc_data *vc; struct vcs_poll_data *poll; - long pos; - long attr, read; - int col, maxcol, viewed; + long pos, read; + int attr, uni_mode, row, col, maxcol, viewed; unsigned short *org = NULL; ssize_t ret; char *con_buf; @@ -218,7 +245,8 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) */ console_lock(); - attr = (currcons & 128); + uni_mode = use_unicode(inode); + attr = use_attributes(inode); ret = -ENXIO; vc = vcs_vc(inode, &viewed); if (!vc) @@ -227,6 +255,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) ret = -EINVAL; if (pos < 0) goto unlock_out; + /* we enforce 32-bit alignment for pos and count in unicode mode */ + if (uni_mode && (pos | count) & 3) + goto unlock_out; + poll = file->private_data; if (count && poll) poll->seen_last_update = true; @@ -266,7 +298,27 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) con_buf_start = con_buf0 = con_buf; orig_count = this_round; maxcol = vc->vc_cols; - if (!attr) { + if (uni_mode) { + unsigned int nr; + + ret = vc_uniscr_check(vc); + if (ret) + break; + p /= 4; + row = p / vc->vc_cols; + col = p % maxcol; + nr = maxcol - col; + do { + if (nr > this_round/4) + nr = this_round/4; + vc_uniscr_copy_line(vc, con_buf0, row, col, nr); + con_buf0 += nr * 4; + this_round -= nr * 4; + row++; + col = 0; + nr = maxcol; + } while (this_round); + } else if (!attr) { org = screen_pos(vc, p, viewed); col = p % maxcol; p += maxcol - col; @@ -375,7 +427,6 @@ static ssize_t vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file_inode(file); - unsigned int currcons = iminor(inode); struct vc_data *vc; long pos; long attr, size, written; @@ -396,7 +447,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) */ console_lock(); - attr = (currcons & 128); + attr = use_attributes(inode); ret = -ENXIO; vc = vcs_vc(inode, &viewed); if (!vc) @@ -593,9 +644,15 @@ vcs_fasync(int fd, struct file *file, int on) static int vcs_open(struct inode *inode, struct file *filp) { - unsigned int currcons = iminor(inode) & 127; + unsigned int currcons = console(inode); + bool attr = use_attributes(inode); + bool uni_mode = use_unicode(inode); int ret = 0; - + + /* we currently don't support attributes in unicode mode */ + if (attr && uni_mode) + return -EOPNOTSUPP; + console_lock(); if(currcons && !vc_cons_allocated(currcons-1)) ret = -ENXIO; @@ -628,6 +685,8 @@ void vcs_make_sysfs(int index) { device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL, "vcs%u", index + 1); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 65), NULL, + "vcsu%u", index + 1); device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL, "vcsa%u", index + 1); } @@ -635,6 +694,7 @@ void vcs_make_sysfs(int index) void vcs_remove_sysfs(int index) { device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 1)); + device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 65)); device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 129)); } @@ -647,6 +707,7 @@ int __init vcs_init(void) vc_class = class_create(THIS_MODULE, "vc"); device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 64), NULL, "vcsu"); device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); for (i = 0; i < MIN_NR_CONSOLES; i++) vcs_make_sysfs(i); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3a801a60f4..2cba6089ca 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -483,6 +483,67 @@ static void vc_uniscr_copy_area(struct uni_screen *dst, } } +/* + * Called from vcs_read() to make sure unicode screen retrieval is possible. + * This will initialize the unicode screen buffer if not already done. + * This returns 0 if OK, or a negative error code otherwise. + * In particular, -ENODATA is returned if the console is not in UTF-8 mode. + */ +int vc_uniscr_check(struct vc_data *vc) +{ + struct uni_screen *uniscr; + unsigned short *p; + int x, y, mask; + + if (__is_defined(NO_VC_UNI_SCREEN)) + return -EOPNOTSUPP; + + WARN_CONSOLE_UNLOCKED(); + + if (!vc->vc_utf) + return -ENODATA; + + if (vc->vc_uni_screen) + return 0; + + uniscr = vc_uniscr_alloc(vc->vc_cols, vc->vc_rows); + if (!uniscr) + return -ENOMEM; + + /* + * Let's populate it initially with (imperfect) reverse translation. + * This is the next best thing we can do short of having it enabled + * from the start even when no users rely on this functionality. True + * unicode content will be available after a complete screen refresh. + */ + p = (unsigned short *)vc->vc_origin; + mask = vc->vc_hi_font_mask | 0xff; + for (y = 0; y < vc->vc_rows; y++) { + char32_t *line = uniscr->lines[y]; + for (x = 0; x < vc->vc_cols; x++) { + u16 glyph = scr_readw(p++) & mask; + line[x] = inverse_translate(vc, glyph, true); + } + } + + vc->vc_uni_screen = uniscr; + return 0; +} + +/* + * Called from vcs_read() to get the unicode data from the screen. + * This must be preceded by a successful call to vc_uniscr_check() once + * the console lock has been taken. + */ +void vc_uniscr_copy_line(struct vc_data *vc, void *dest, + unsigned int row, unsigned int col, unsigned int nr) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + + BUG_ON(!uniscr); + memcpy(dest, &uniscr->lines[row][col], nr * sizeof(char32_t)); +} + static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b, enum con_scroll dir, unsigned int nr) diff --git a/include/linux/selection.h b/include/linux/selection.h index 5b278ce99d..2b34df9f1e 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -42,4 +42,9 @@ extern u16 vcs_scr_readw(struct vc_data *vc, const u16 *org); extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); extern void vcs_scr_updated(struct vc_data *vc); +extern int vc_uniscr_check(struct vc_data *vc); +extern void vc_uniscr_copy_line(struct vc_data *vc, void *dest, + unsigned int row, unsigned int col, + unsigned int nr); + #endif From patchwork Wed May 30 21:27:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 137294 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp5817398lji; Wed, 30 May 2018 14:29:34 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKVoxqBeCYQ7jvtzSylwzdYsQsk0lHGfiCzoaRVSqAuVlLcjtUYOGBUGraame1xB0M1diTa X-Received: by 2002:a63:3348:: with SMTP id z69-v6mr69765pgz.171.1527715773993; Wed, 30 May 2018 14:29:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527715773; cv=none; d=google.com; s=arc-20160816; b=pMlnvwD4nXPaYjpsZ8FKF5UqBjRY+iVqw3Zyn/mR89Gbau1WyWYopBESbn7VBqUSJa 4duZfNkKt5Vfcni6UgkdMaMPiUhEzVaijCs8kbjd8PfTFBobXPl+VJ7Srv2Xzi1emAtZ On5RUClBy4VyxZ5Z+5JncvToISqbepDU62GFq7xZTj0qzDdglHAKzfZkseETRwVpIYn2 AxJV4v/0EqdZ28A77r5f4e5/ZmqgJ41dyHLiov3m1tOg48Vpb4+jhV/wzz/deFmITftD BReGpjM6F9X45Tbm6IGJMezMxLdX6j0n0UIfCKooBuT4AfHGRn0uCBcKiAwTeylp2NfZ zkVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=iAjb683DhMOW6yqjytXqBoz3NYNKYs8M2FBnsUSkbRw=; b=O/YnOnbsvR2g1nMKkLSnVroQJ4rD1XmPc/l/5ODQbEWIMWxbuC65FeSlRoBOQDe9dh 1/zaQlUciJEm0iCDu/zdIROtCQW57VrZm3ae/BCXReijO9nmoyq6JZc9VM2A4o1kCEp4 UvkkJqejpo9E+OvmrOkE1aAKEJ10mGAGatmR4A3gkDq+R6JvCYsJ/CZ5Oid2pMs7m+Tx IYAwfr3xA8NEcdd6AmGQMwNAUQ2Yup3qts+uFw395j8kEQ4NvV8Hzw0DGJYPDdE3qJjS gFzuGsyVjfGVwGniSs9+bmdDqOIk67DoGmiAidSbHgXnoRGrRMRaCAGd4rte+9xTVO3K 8+kQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=SFyfKDGF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c14-v6si18592699plo.359.2018.05.30.14.29.33; Wed, 30 May 2018 14:29:33 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=SFyfKDGF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932653AbeE3V3b (ORCPT + 30 others); Wed, 30 May 2018 17:29:31 -0400 Received: from pb-smtp2.pobox.com ([64.147.108.71]:62606 "EHLO pb-smtp2.pobox.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932300AbeE3V2V (ORCPT ); Wed, 30 May 2018 17:28:21 -0400 Received: from pb-smtp2.pobox.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 6CFCFF351A; Wed, 30 May 2018 17:28:19 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=sasl; bh=9DAw iQEBBOWmo4PgLUwwV9ngQQ4=; b=SFyfKDGF8nG1Ic0ZlnMC7bw4Wq9ptw3sUgUb 7GxXfyDsnB6QUscuZRyyadjZbM0o4bxXpf4SXwG9JeuFT+6zu4a0xJU70sjZM+m0 NSq2c7e7C6JrKt6nA7knLywwExC9/EKC3ZX/Q6P4tWzkzweA8F9nCi2m7l7+1elY TN0Qn48= Received: from pb-smtp2.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp2.pobox.com (Postfix) with ESMTP id 63C48F3519; Wed, 30 May 2018 17:28:19 -0400 (EDT) Received: from yoda.home (unknown [70.82.104.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp2.pobox.com (Postfix) with ESMTPSA id E0416F3512; Wed, 30 May 2018 17:28:18 -0400 (EDT) Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id 2D2C22DA06B7; Wed, 30 May 2018 17:28:18 -0400 (EDT) From: Nicolas Pitre To: Greg Kroah-Hartman Cc: Dave Mielke , Samuel Thibault , linux-kernel@vger.kernel.org Subject: [PATCH 4/5] vt: unicode fallback for scrollback Date: Wed, 30 May 2018 17:27:44 -0400 Message-Id: <20180530212745.10997-5-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530212745.10997-1-nicolas.pitre@linaro.org> References: <20180530212745.10997-1-nicolas.pitre@linaro.org> X-Pobox-Relay-ID: 5F0906B6-6450-11E8-B454-67830C78B957-78420484!pb-smtp2.pobox.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org There is currently no provision for scrollback content in the core code, leaving that to backend video drivers where this can be highly optimized. There is currently no common method for those drivers to tell the core what part of the scrollback is actually displayed and what size the scrollback buffer is either. Because of that, the unicode screen buffer has no provision for any scrollback. At least we can provide backtranslated glyph values when the scrollback is active which should be plenty good enough for now. Signed-off-by: Nicolas Pitre Tested-by: Dave Mielke --- drivers/tty/vt/vc_screen.c | 3 ++- drivers/tty/vt/vt.c | 31 +++++++++++++++++++++++++++++-- include/linux/selection.h | 2 +- 3 files changed, 32 insertions(+), 4 deletions(-) -- 2.17.0 diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 9c44252e52..2384ea85ff 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -311,7 +311,8 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) do { if (nr > this_round/4) nr = this_round/4; - vc_uniscr_copy_line(vc, con_buf0, row, col, nr); + vc_uniscr_copy_line(vc, con_buf0, viewed, + row, col, nr); con_buf0 += nr * 4; this_round -= nr * 4; row++; diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2cba6089ca..e7c3cabeb1 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -535,13 +535,40 @@ int vc_uniscr_check(struct vc_data *vc) * This must be preceded by a successful call to vc_uniscr_check() once * the console lock has been taken. */ -void vc_uniscr_copy_line(struct vc_data *vc, void *dest, +void vc_uniscr_copy_line(struct vc_data *vc, void *dest, int viewed, unsigned int row, unsigned int col, unsigned int nr) { struct uni_screen *uniscr = get_vc_uniscr(vc); + int offset = row * vc->vc_size_row + col * 2; + unsigned long pos; BUG_ON(!uniscr); - memcpy(dest, &uniscr->lines[row][col], nr * sizeof(char32_t)); + + pos = (unsigned long)screenpos(vc, offset, viewed); + if (pos >= vc->vc_origin && pos < vc->vc_scr_end) { + /* + * Desired position falls in the main screen buffer. + * However the actual row/col might be different if + * scrollback is active. + */ + row = (pos - vc->vc_origin) / vc->vc_size_row; + col = ((pos - vc->vc_origin) % vc->vc_size_row) / 2; + memcpy(dest, &uniscr->lines[row][col], nr * sizeof(char32_t)); + } else { + /* + * Scrollback is active. For now let's simply backtranslate + * the screen glyphs until the unicode screen buffer does + * synchronize with console display drivers for a scrollback + * buffer of its own. + */ + u16 *p = (u16 *)pos; + int mask = vc->vc_hi_font_mask | 0xff; + char32_t *uni_buf = dest; + while (nr--) { + u16 glyph = scr_readw(p++) & mask; + *uni_buf++ = inverse_translate(vc, glyph, true); + } + } } diff --git a/include/linux/selection.h b/include/linux/selection.h index 2b34df9f1e..067d2e99c7 100644 --- a/include/linux/selection.h +++ b/include/linux/selection.h @@ -43,7 +43,7 @@ extern void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org); extern void vcs_scr_updated(struct vc_data *vc); extern int vc_uniscr_check(struct vc_data *vc); -extern void vc_uniscr_copy_line(struct vc_data *vc, void *dest, +extern void vc_uniscr_copy_line(struct vc_data *vc, void *dest, int viewed, unsigned int row, unsigned int col, unsigned int nr); From patchwork Wed May 30 21:27:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 137289 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp5816483lji; Wed, 30 May 2018 14:28:25 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJGsEzVM4WWgTfcW+AeyeHksypBF/qd8qBALUSlqdLMwyS8+Lg1GMhAxEZpk8m6xKg/n/J/ X-Received: by 2002:a17:902:9344:: with SMTP id g4-v6mr4443200plp.10.1527715705269; Wed, 30 May 2018 14:28:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527715705; cv=none; d=google.com; s=arc-20160816; b=cyZj1w0vR2cQy/pQooJShwDJmhuC7HNfPrm8AhtjoVLJUXx/z7xmXHA0DzkBv+OSLC hKRbM3rH/b/wIlpgL+A2QvkNkorTshd/7BiUHB51Nx4xTlxe+hKGrgCWw2rRf+3+Zr48 UzO7Cdn82dlD0k8WepKFosTlnGoAKcW58Lh5/vGC360GRHX6odQd+6UzbRqwtD1L5pn5 1jwNNxEw/0r7luPgo8VmPDQNl3vbozxe8k7en39eE2mIz2wJA9e9gWK/ZA0ISbkvGdRf NVTpszqSpOmVG3pP77fO2kqgkt0u6ohR52zPNRRZ06KTn0xAnmzKShaC3sgyPvOI6Ut5 krEg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=MITpJEubxL70uT4SzIKN0Bw9x+DxazT4+YHNUQFZcJc=; b=jd2UlaKWE7pc6kH58KqeS0W1dNPNMyE/e5xUIQUD5xoj+H60JBejvEtKlengimRco7 8GnhQ6+ux84RRLV5DSkzE51+DjbyXqMDAGQOnDeIyPrOOli4hgu00EndFREyTF3o2ULL UH1K812rjQ/gseo/gk2z0eP2JLABywW43Jn+opUikRYIUIlxj6GIVDHfPcZUU01B3NX6 fTbcf3QN2q0hvsBj9//+7Fu4GEGtA2EDHbkL0m5J+zKhb07MyIcoLPd8OgrRc6QIFfDD nM8T6xbTT1xsfhAwyO7F6EiGMrAUhqJZZUDAc5CAVVKMZmDCLvtu/3veUe4SSE4POmM3 TC+g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=xn8GTcWw; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 5-v6si36237263plx.517.2018.05.30.14.28.25; Wed, 30 May 2018 14:28:25 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@pobox.com header.s=sasl header.b=xn8GTcWw; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932540AbeE3V2X (ORCPT + 30 others); Wed, 30 May 2018 17:28:23 -0400 Received: from pb-smtp1.pobox.com ([64.147.108.70]:61993 "EHLO pb-smtp1.pobox.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932254AbeE3V2V (ORCPT ); Wed, 30 May 2018 17:28:21 -0400 Received: from pb-smtp1.pobox.com (unknown [127.0.0.1]) by pb-smtp1.pobox.com (Postfix) with ESMTP id 17FEDF2C64; Wed, 30 May 2018 17:28:20 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=pobox.com; h=from:to:cc :subject:date:message-id:in-reply-to:references; s=sasl; bh=OmZ1 4W9Q5TZKUZeQmrd/ZWdG3C8=; b=xn8GTcWwtooPZ9EzlJwPkgN1BcRzemaxTl7r +vekZ7AHAGBcBHypWNpaOM0fMgpneugFSa2ElkgAkTCco/4JLLRHQwUpBlbg5KLL 2LKOYiVCihpYJMEFXPDpmEew/EX7go7F5LIyZtr0Hy51WmSopUM+dm6w3f1Xe3xr WjCQzVw= Received: from pb-smtp1.nyi.icgroup.com (unknown [127.0.0.1]) by pb-smtp1.pobox.com (Postfix) with ESMTP id 0EBA7F2C63; Wed, 30 May 2018 17:28:20 -0400 (EDT) Received: from yoda.home (unknown [70.82.104.228]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by pb-smtp1.pobox.com (Postfix) with ESMTPSA id 8A676F2C62; Wed, 30 May 2018 17:28:19 -0400 (EDT) Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id 464962DA06B8; Wed, 30 May 2018 17:28:18 -0400 (EDT) From: Nicolas Pitre To: Greg Kroah-Hartman Cc: Dave Mielke , Samuel Thibault , linux-kernel@vger.kernel.org Subject: [PATCH 5/5] vt: coherence validation code for the unicode screen buffer Date: Wed, 30 May 2018 17:27:45 -0400 Message-Id: <20180530212745.10997-6-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180530212745.10997-1-nicolas.pitre@linaro.org> References: <20180530212745.10997-1-nicolas.pitre@linaro.org> X-Pobox-Relay-ID: 5F6B0AE6-6450-11E8-8574-44CE1968708C-78420484!pb-smtp1.pobox.com Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Make sure the unicode screen buffer matches the video screen content. This is provided for debugging convenience and disabled by default. Signed-off-by: Nicolas Pitre --- drivers/tty/vt/vt.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) -- 2.17.0 diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index e7c3cabeb1..2f3d528082 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -571,6 +571,45 @@ void vc_uniscr_copy_line(struct vc_data *vc, void *dest, int viewed, } } +/* this is for validation and debugging only */ +static void vc_uniscr_debug_check(struct vc_data *vc) +{ + struct uni_screen *uniscr = get_vc_uniscr(vc); + unsigned short *p; + int x, y, mask; + + if (true) + return; + + if (!uniscr) + return; + + WARN_CONSOLE_UNLOCKED(); + + /* + * Make sure our unicode screen translates into the same glyphs + * as the actual screen. This is brutal indeed. + */ + p = (unsigned short *)vc->vc_origin; + mask = vc->vc_hi_font_mask | 0xff; + for (y = 0; y < vc->vc_rows; y++) { + char32_t *line = uniscr->lines[y]; + for (x = 0; x < vc->vc_cols; x++) { + u16 glyph = scr_readw(p++) & mask; + char32_t uc = line[x]; + int tc = conv_uni_to_pc(vc, uc); + if (tc == -4) + tc = conv_uni_to_pc(vc, 0xfffd); + if (tc == -4) + tc = conv_uni_to_pc(vc, '?'); + if (tc != glyph) + pr_notice("%s: mismatch at %d,%d: " + "glyph=%#x tc=%#x\n", __func__, + x, y, glyph, tc); + } + } +} + static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b, enum con_scroll dir, unsigned int nr) @@ -2719,6 +2758,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co do_con_trol(tty, vc, orig); } con_flush(vc, draw_from, draw_to, &draw_x); + vc_uniscr_debug_check(vc); console_conditional_schedule(); console_unlock(); notify_update(vc);