From nobody Sat Nov 15 03:36:22 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1589984705; cv=none; d=zohomail.com; s=zohoarc; b=N55aF6FGvdO+bK67NT+y3nxTWAj4sM27xNrNVJH4RkVboDKiZ+XKgVNz1gRdnR17BW3nox2hYNHrbAL1Pb/5b8OuA2/pkdY+8w5NCKjw8RzwBN0OloP2Q4uU0znbm7VvUi4KrnKA2gZwU+pcnhweTCocIOrRskIDCbfGJKLf5yg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1589984705; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To; bh=iuIhaYi2SG7g97Gut4hLXKQqrYSVcIT1lsvnltO4haM=; b=NSKIp6cSBpv8luwW7zi5kewINCMfTylZlz4ff7wtboklMMoleAmL3LGXd0EZ7aK5QlJZjaGgbVTplRSbR9rfkUSYxiHWbNvmr5LMnuj94IARSp3RLS7j3d6UQFXkEcNh2zFP+XoUW13A/L1vEktC13WOf/cikjLdxDExKTOVCic= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1589984705366681.6368324423752; Wed, 20 May 2020 07:25:05 -0700 (PDT) Received: from localhost ([::1]:48240 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jbPeY-0001P2-Jq for importer@patchew.org; Wed, 20 May 2020 10:25:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:57126) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jbPXn-0004zt-Ro for qemu-devel@nongnu.org; Wed, 20 May 2020 10:18:03 -0400 Received: from zero.eik.bme.hu ([152.66.115.2]:49725) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jbPXk-0004Pw-Ag for qemu-devel@nongnu.org; Wed, 20 May 2020 10:18:03 -0400 Received: from zero.eik.bme.hu (blah.eik.bme.hu [152.66.115.182]) by localhost (Postfix) with SMTP id 940DA748DCF; Wed, 20 May 2020 16:17:49 +0200 (CEST) Received: by zero.eik.bme.hu (Postfix, from userid 432) id 44EFF748DCC; Wed, 20 May 2020 16:17:49 +0200 (CEST) Message-Id: In-Reply-To: References: From: BALATON Zoltan Subject: [PATCH 5/6] sm501: Replace hand written implementation with pixman where possible Date: Wed, 20 May 2020 15:39:50 +0200 To: qemu-devel@nongnu.org X-Spam-Probability: 8% Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=152.66.115.2; envelope-from=balaton@eik.bme.hu; helo=zero.eik.bme.hu X-detected-operating-system: by eggs.gnu.org: First seen = 2020/05/20 10:17:49 X-ACL-Warn: Detected OS = FreeBSD 9.x or newer [fuzzy] X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , Sebastian Bauer , Magnus Damm , Gerd Hoffmann , Aurelien Jarno Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Besides being faster this should also prevent malicious guests to abuse 2D engine to overwrite data or cause a crash. Signed-off-by: BALATON Zoltan --- hw/display/sm501.c | 181 +++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 88 deletions(-) diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 5ed57703d8..13269cc9f4 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -706,13 +706,12 @@ static void sm501_2d_operation(SM501State *s) /* 1 if rop2 source is the pattern, otherwise the source is the bitmap= */ int rop2_source_is_pattern =3D (s->twoD_control >> 14) & 0x1; int rop =3D s->twoD_control & 0xFF; - int dst_x =3D (s->twoD_destination >> 16) & 0x01FFF; - int dst_y =3D s->twoD_destination & 0xFFFF; - int width =3D (s->twoD_dimension >> 16) & 0x1FFF; - int height =3D s->twoD_dimension & 0xFFFF; + unsigned int dst_x =3D (s->twoD_destination >> 16) & 0x01FFF; + unsigned int dst_y =3D s->twoD_destination & 0xFFFF; + unsigned int width =3D (s->twoD_dimension >> 16) & 0x1FFF; + unsigned int height =3D s->twoD_dimension & 0xFFFF; uint32_t dst_base =3D s->twoD_destination_base & 0x03FFFFFF; - uint8_t *dst =3D s->local_mem + dst_base; - int dst_pitch =3D (s->twoD_pitch >> 16) & 0x1FFF; + unsigned int dst_pitch =3D (s->twoD_pitch >> 16) & 0x1FFF; int crt =3D (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0; int fb_len =3D get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt= ); =20 @@ -721,104 +720,110 @@ static void sm501_2d_operation(SM501State *s) return; } =20 - if (rop_mode =3D=3D 0) { - if (rop !=3D 0xcc) { - /* Anything other than plain copies are not supported */ - qemu_log_mask(LOG_UNIMP, "sm501: rop3 mode with rop %x is not " - "supported.\n", rop); - } - } else { - if (rop2_source_is_pattern && rop !=3D 0x5) { - /* For pattern source, we support only inverse dest */ - qemu_log_mask(LOG_UNIMP, "sm501: rop2 source being the pattern= and " - "rop %x is not supported.\n", rop); - } else { - if (rop !=3D 0x5 && rop !=3D 0xc) { - /* Anything other than plain copies or inverse dest is not - * supported */ - qemu_log_mask(LOG_UNIMP, "sm501: rop mode %x is not " - "supported.\n", rop); - } - } - } - if (s->twoD_source_base & BIT(27) || s->twoD_destination_base & BIT(27= )) { qemu_log_mask(LOG_UNIMP, "sm501: only local memory is supported.\n= "); return; } =20 + if (!dst_pitch) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero dest pitch.\n"); + return; + } + + if (!width || !height) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero size 2D op.\n"); + return; + } + + /* Do we need to handle overlapping regions? */ + if (rtl) { + dst_x -=3D width - 1; + dst_y -=3D height - 1; + } + + if (dst_base >=3D get_local_mem_size(s) || + dst_base + (dst_x + width + (dst_y + height) * dst_pitch) * + (1 << format) >=3D get_local_mem_size(s)) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.= \n"); + return; + } + switch (cmd) { - case 0x00: /* copy area */ + case 0: /* BitBlt */ { - int src_x =3D (s->twoD_source >> 16) & 0x01FFF; - int src_y =3D s->twoD_source & 0xFFFF; + unsigned int src_x =3D (s->twoD_source >> 16) & 0x01FFF; + unsigned int src_y =3D s->twoD_source & 0xFFFF; uint32_t src_base =3D s->twoD_source_base & 0x03FFFFFF; - uint8_t *src =3D s->local_mem + src_base; - int src_pitch =3D s->twoD_pitch & 0x1FFF; - -#define COPY_AREA(_bpp, _pixel_type, rtl) { = \ - int y, x, index_d, index_s; = \ - for (y =3D 0; y < height; y++) { \ - for (x =3D 0; x < width; x++) { \ - _pixel_type val; = \ - = \ - if (rtl) { = \ - index_s =3D ((src_y - y) * src_pitch + src_x - x) * _b= pp; \ - index_d =3D ((dst_y - y) * dst_pitch + dst_x - x) * _b= pp; \ - } else { = \ - index_s =3D ((src_y + y) * src_pitch + src_x + x) * _b= pp; \ - index_d =3D ((dst_y + y) * dst_pitch + dst_x + x) * _b= pp; \ - } = \ - if (rop_mode =3D=3D 1 && rop =3D=3D 5) { = \ - /* Invert dest */ = \ - val =3D ~*(_pixel_type *)&dst[index_d]; = \ - } else { = \ - val =3D *(_pixel_type *)&src[index_s]; = \ - } = \ - *(_pixel_type *)&dst[index_d] =3D val; = \ - } = \ - } = \ - } - switch (format) { - case 0: - COPY_AREA(1, uint8_t, rtl); - break; - case 1: - COPY_AREA(2, uint16_t, rtl); - break; - case 2: - COPY_AREA(4, uint32_t, rtl); - break; + unsigned int src_pitch =3D s->twoD_pitch & 0x1FFF; + + if (!src_pitch) { + qemu_log_mask(LOG_GUEST_ERROR, "sm501: Zero src pitch.\n"); + return; + } + + if (rtl) { + src_x -=3D width - 1; + src_y -=3D height - 1; + } + + if (src_base >=3D get_local_mem_size(s) || + src_base + (src_x + width + (src_y + height) * src_pitch) * + (1 << format) >=3D get_local_mem_size(s)) { + qemu_log_mask(LOG_GUEST_ERROR, + "sm501: 2D op src is outside vram.\n"); + return; + } + + if ((rop_mode && rop =3D=3D 0x5) || (!rop_mode && rop =3D=3D 0x55)= ) { + /* Invert dest, is there a way to do this with pixman? */ + unsigned int x, y, i; + uint8_t *d =3D s->local_mem + dst_base; + + for (y =3D 0; y < height; y++) { + i =3D (dst_x + (dst_y + y) * dst_pitch) * (1 << format); + for (x =3D 0; x < width; x++, i +=3D (1 << format)) { + switch (format) { + case 0: + d[i] =3D ~d[i]; + break; + case 1: + *(uint16_t *)&d[i] =3D ~*(uint16_t *)&d[i]; + break; + case 2: + *(uint32_t *)&d[i] =3D ~*(uint32_t *)&d[i]; + break; + } + } + } + } else if ((rop_mode && rop =3D=3D 0xc && !rop2_source_is_pattern)= || + (!rop_mode && rop =3D=3D 0xcc)) { + /* Do copy src directly */ + pixman_blt((uint32_t *)&s->local_mem[src_base], + (uint32_t *)&s->local_mem[dst_base], + src_pitch * (1 << format) / sizeof(uint32_t), + dst_pitch * (1 << format) / sizeof(uint32_t), + 8 * (1 << format), 8 * (1 << format), + src_x, src_y, dst_x, dst_y, width, height); + } else { + qemu_log_mask(LOG_UNIMP, "sm501: rop%d op %x%s not implemented= \n", + (rop_mode ? 2 : 3), rop, (rop2_source_is_pattern= ? + " with pattern source" : "")); } break; } - case 0x01: /* fill rectangle */ + case 1: /* Rectangle Fill */ { uint32_t color =3D s->twoD_foreground; =20 -#define FILL_RECT(_bpp, _pixel_type) { = \ - int y, x; = \ - for (y =3D 0; y < height; y++) { \ - for (x =3D 0; x < width; x++) { \ - int index =3D ((dst_y + y) * dst_pitch + dst_x + x) * _bpp= ; \ - *(_pixel_type *)&dst[index] =3D (_pixel_type)color; = \ - } = \ - } = \ - } - - switch (format) { - case 0: - FILL_RECT(1, uint8_t); - break; - case 1: - color =3D cpu_to_le16(color); - FILL_RECT(2, uint16_t); - break; - case 2: + if (format =3D=3D 2) { color =3D cpu_to_le32(color); - FILL_RECT(4, uint32_t); - break; + } else if (format =3D=3D 1) { + color =3D cpu_to_le16(color); } + + pixman_fill((uint32_t *)&s->local_mem[dst_base], + dst_pitch * (1 << format) / sizeof(uint32_t), + 8 * (1 << format), dst_x, dst_y, width, height, color); break; } default: --=20 2.21.3