From nobody Mon Nov 3 06:32:39 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=cloud.com ARC-Seal: i=1; a=rsa-sha256; t=1731433032; cv=none; d=zohomail.com; s=zohoarc; b=CaNISrXRwq8khN6AIZ+rydhnMap+NRa9FWy8twVuGYNFPoJfgOywHBoP81INBmYQGRDJThkgIUOfa0QuSS20js3ZNBIbC03x9jpTk/jpPqci94JonmDmsz1EMxaU8zF57sGvEu52N0xaA911H6C2RdoP/L1iouAJHpRjFuB1+AU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1731433032; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=4dHtb4C0WC3jTkiClRLTbwiGLDfIKgOfntISQe9iTE8=; b=QIDB+lB+eTJ/UKvBmKJ4m8ezO1ZRVTqAbLX7PYulh//gnso2hK30P5OoMiU6sMiaWPVUL+fZWwHB/mJ0UumXaFpBuoDrFAUw4pcSVMWz92Ru2Mh0yPy/q1OClEBp3ZGe3E5RSNHYcVbUPvrR0wzyUxVUdKS6W98Cw6vWfazyMQU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1731433032879918.0243356652317; Tue, 12 Nov 2024 09:37:12 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.834865.1250662 (Exim 4.92) (envelope-from ) id 1tAuoo-000659-Jr; Tue, 12 Nov 2024 17:36:46 +0000 Received: by outflank-mailman (output) from mailman id 834865.1250662; Tue, 12 Nov 2024 17:36:46 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tAuoo-000652-HF; Tue, 12 Nov 2024 17:36:46 +0000 Received: by outflank-mailman (input) for mailman id 834865; Tue, 12 Nov 2024 17:36:45 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1tAuon-00064w-ET for xen-devel@lists.xenproject.org; Tue, 12 Nov 2024 17:36:45 +0000 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [2a00:1450:4864:20::634]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id ac8109b6-a11c-11ef-a0c7-8be0dac302b0; Tue, 12 Nov 2024 18:36:39 +0100 (CET) Received: by mail-ej1-x634.google.com with SMTP id a640c23a62f3a-a9a628b68a7so1055396166b.2 for ; Tue, 12 Nov 2024 09:36:40 -0800 (PST) Received: from mbarnes-x-u.eng.citrite.net ([185.25.67.249]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a9ee0deef3esm746325966b.141.2024.11.12.09.36.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 09:36:38 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: ac8109b6-a11c-11ef-a0c7-8be0dac302b0 X-Custom-Connection: eyJyZW1vdGVpcCI6IjJhMDA6MTQ1MDo0ODY0OjIwOjo2MzQiLCJoZWxvIjoibWFpbC1lajEteDYzNC5nb29nbGUuY29tIn0= X-Custom-Transaction: eyJpZCI6ImFjODEwOWI2LWExMWMtMTFlZi1hMGM3LThiZTBkYWMzMDJiMCIsInRzIjoxNzMxNDMyOTk5Ljg2NzQyNiwic2VuZGVyIjoibWF0dGhldy5iYXJuZXNAY2xvdWQuY29tIiwicmVjaXBpZW50IjoieGVuLWRldmVsQGxpc3RzLnhlbnByb2plY3Qub3JnIn0= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1731432999; x=1732037799; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=4dHtb4C0WC3jTkiClRLTbwiGLDfIKgOfntISQe9iTE8=; b=S+Q8GX+7T4fIQLdJVVDqG5VN3mfU/aITZTiczya1/JU96j3D+qZ7STSaY/eu2pLPc0 2Nn+gox0uOjq49DtP+s+OXquEEd73zd5zOTszBfVG5l96mw7I1CAafoL8dl0s7IZgTuy FgzKg2bUocGzLUb3WHHxzMgFzUnM5aNA2QWxc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731432999; x=1732037799; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=4dHtb4C0WC3jTkiClRLTbwiGLDfIKgOfntISQe9iTE8=; b=VincPFrJjjYfl4EaTCO6gpdExgtv2+Zh3lmRZ5oo1KB4ZsVggMaj5eEDq9QxOdAv8z 5IcT7c7JAa+4Oy2k39ZFKWGBX1dWBqAuwbIV0niucqqetqJ0V4eo2ufiQoUfNw9tSg5P Q4pLIk9os8CqgnHZdIVEVfDMrrssvvrJKcZXNPHVaajrAZZWpFAqaCsT9JL+ywlREjgG m+DXukNaLf42pDBmGYu4yPOuRGQzCuDilNsHfCOAP7uHZgTyl2gJBJpGuVrwPQQva/O/ zUsRBi80VSUJVtQiN958JYS6ShDVL7TAczRj7I6Bv8IB3D1XGUb1dC/cCtDdSsi6alcg 5iMw== X-Gm-Message-State: AOJu0YxXAxUSk2hMh66XQ3Gv+9xppy4hotNuexT+1UJizxXV2wx4dW8S tjcR5Vf2qyN0q5C+o+0P9NMli9F6sJVjP3ft0hoM2ILr9BvLNFIV+hRcpXMCtnqVKVkee5fd0E/ 4 X-Google-Smtp-Source: AGHT+IF0UOvRLGygklKcZJ+srfbdfCdYMlXr8+i6cu93V0/IYVMXEHgrVOpu64PJntugmVoOZKs7rg== X-Received: by 2002:a17:906:6a20:b0:a99:61d1:348f with SMTP id a640c23a62f3a-a9ef0016c58mr1634215166b.52.1731432999128; Tue, 12 Nov 2024 09:36:39 -0800 (PST) From: Matthew Barnes To: xen-devel@lists.xenproject.org Cc: Matthew Barnes , Andrew Cooper Subject: [XTF PATCH] Misaligned I/O Breakpoints Date: Tue, 12 Nov 2024 17:22:46 +0000 Message-Id: X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Bcc: Matthew Barnes Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @cloud.com) X-ZM-MESSAGEID: 1731433034671116600 Content-Type: text/plain; charset="utf-8" This xtf test tests a bug to hardware IO port breakpoints fixed by 08aacc392d86 ("x86/emul: Fix misaligned IO breakpoint behaviour in PV guest= s") Signed-off-by: Matthew Barnes --- docs/all-tests.dox | 2 + tests/misaligned-io-breakpoints/Makefile | 9 + tests/misaligned-io-breakpoints/main.c | 283 +++++++++++++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 tests/misaligned-io-breakpoints/Makefile create mode 100644 tests/misaligned-io-breakpoints/main.c diff --git a/docs/all-tests.dox b/docs/all-tests.dox index 0a8b9130cfe8..66e35babe4d7 100644 --- a/docs/all-tests.dox +++ b/docs/all-tests.dox @@ -41,6 +41,8 @@ Coveres XSA-106 and XSA-156. =20 @subpage test-umip - Guest User-Mode Instruction Prevention support. =20 +@subpage test-misaligned-io-breakpoints - Misaligned I/O port hardware bre= akpoint test. + =20 @section index-xsa XSA Proof-of-Concept tests =20 diff --git a/tests/misaligned-io-breakpoints/Makefile b/tests/misaligned-io= -breakpoints/Makefile new file mode 100644 index 000000000000..9e4cd3eef761 --- /dev/null +++ b/tests/misaligned-io-breakpoints/Makefile @@ -0,0 +1,9 @@ +include $(ROOT)/build/common.mk + +NAME :=3D misaligned-io-breakpoints +CATEGORY :=3D utility +TEST-ENVS :=3D pv64 + +obj-perenv +=3D main.o + +include $(ROOT)/build/gen.mk diff --git a/tests/misaligned-io-breakpoints/main.c b/tests/misaligned-io-b= reakpoints/main.c new file mode 100644 index 000000000000..d91222b29288 --- /dev/null +++ b/tests/misaligned-io-breakpoints/main.c @@ -0,0 +1,283 @@ +/** + * @file tests/misaligned-io-breakpoints/main.c + * @ref test-misaligned-io-breakpoints - Misaligned I/O port hardware brea= kpoint test. + * + * @page test-misaligned-io-breakpoints Misaligned I/O Breakpoints + * + * When hardware breakpoints are configured on misaligned IO ports, the + * hardware will mask the addresses based on the breakpoint width during + * comparison. + * + * This test checks that the emulated behaviour of misaligned IO breakpoin= ts + * in PV guests match that of real hardware. + * + * @see tests/io-breakpoint-bug/main.c + */ +#include + +enum width { _16, _32 }; + +const char test_title[] =3D "Misaligned I/O Breakpoints"; + +static const struct test { + unsigned long breakpoint_port; + enum width breakpoint_size; + uint16_t io_op_port; + enum width io_op_len; + bool expect_breakpoint_trigger; +} tests[] =3D { + /* 16-bit breakpoint, 16-bit I/O operation */ + { 0x09, _16, 0x06, _16, false }, + { 0x09, _16, 0x07, _16, true }, + { 0x09, _16, 0x08, _16, true }, + { 0x09, _16, 0x09, _16, true }, + { 0x09, _16, 0x0a, _16, false }, + + { 0x0b, _16, 0x08, _16, false }, + { 0x0b, _16, 0x09, _16, true }, + { 0x0b, _16, 0x0a, _16, true }, + { 0x0b, _16, 0x0b, _16, true }, + { 0x0b, _16, 0x0c, _16, false }, + + /* 16-bit breakpoint, 32-bit I/O operation */ + { 0x09, _16, 0x04, _32, false }, + { 0x09, _16, 0x05, _32, true }, + { 0x09, _16, 0x06, _32, true }, + { 0x09, _16, 0x07, _32, true }, + { 0x09, _16, 0x08, _32, true }, + { 0x09, _16, 0x09, _32, true }, + { 0x09, _16, 0x0a, _32, false }, + + { 0x0b, _16, 0x06, _32, false }, + { 0x0b, _16, 0x07, _32, true }, + { 0x0b, _16, 0x08, _32, true }, + { 0x0b, _16, 0x09, _32, true }, + { 0x0b, _16, 0x0a, _32, true }, + { 0x0b, _16, 0x0b, _32, true }, + { 0x0b, _16, 0x0c, _32, false }, + + /* 32-bit breakpoint, 16-bit I/O operation */ + { 0x09, _32, 0x06, _16, false }, + { 0x09, _32, 0x07, _16, true }, + { 0x09, _32, 0x08, _16, true }, + { 0x09, _32, 0x09, _16, true }, + { 0x09, _32, 0x0a, _16, true }, + { 0x09, _32, 0x0b, _16, true }, + { 0x09, _32, 0x0c, _16, false }, + + { 0x0a, _32, 0x06, _16, false }, + { 0x0a, _32, 0x07, _16, true }, + { 0x0a, _32, 0x08, _16, true }, + { 0x0a, _32, 0x09, _16, true }, + { 0x0a, _32, 0x0a, _16, true }, + { 0x0a, _32, 0x0b, _16, true }, + { 0x0a, _32, 0x0c, _16, false }, + + { 0x0b, _32, 0x06, _16, false }, + { 0x0b, _32, 0x07, _16, true }, + { 0x0b, _32, 0x08, _16, true }, + { 0x0b, _32, 0x09, _16, true }, + { 0x0b, _32, 0x0a, _16, true }, + { 0x0b, _32, 0x0b, _16, true }, + { 0x0b, _32, 0x0c, _16, false }, + + { 0x0d, _32, 0x0a, _16, false }, + { 0x0d, _32, 0x0b, _16, true }, + { 0x0d, _32, 0x0c, _16, true }, + { 0x0d, _32, 0x0d, _16, true }, + { 0x0d, _32, 0x0e, _16, true }, + { 0x0d, _32, 0x0f, _16, true }, + { 0x0d, _32, 0x10, _16, false }, + + { 0x0e, _32, 0x0a, _16, false }, + { 0x0e, _32, 0x0b, _16, true }, + { 0x0e, _32, 0x0c, _16, true }, + { 0x0e, _32, 0x0d, _16, true }, + { 0x0e, _32, 0x0e, _16, true }, + { 0x0e, _32, 0x0f, _16, true }, + { 0x0e, _32, 0x10, _16, false }, + + { 0x0f, _32, 0x0a, _16, false }, + { 0x0f, _32, 0x0b, _16, true }, + { 0x0f, _32, 0x0c, _16, true }, + { 0x0f, _32, 0x0d, _16, true }, + { 0x0f, _32, 0x0e, _16, true }, + { 0x0f, _32, 0x0f, _16, true }, + { 0x0f, _32, 0x10, _16, false }, + + /* 32-bit breakpoint, 32-bit I/O operation */ + { 0x09, _32, 0x04, _32, false }, + { 0x09, _32, 0x05, _32, true }, + { 0x09, _32, 0x06, _32, true }, + { 0x09, _32, 0x07, _32, true }, + { 0x09, _32, 0x08, _32, true }, + { 0x09, _32, 0x09, _32, true }, + { 0x09, _32, 0x0a, _32, true }, + { 0x09, _32, 0x0b, _32, true }, + { 0x09, _32, 0x0c, _32, false }, + + { 0x0a, _32, 0x04, _32, false }, + { 0x0a, _32, 0x05, _32, true }, + { 0x0a, _32, 0x06, _32, true }, + { 0x0a, _32, 0x07, _32, true }, + { 0x0a, _32, 0x08, _32, true }, + { 0x0a, _32, 0x09, _32, true }, + { 0x0a, _32, 0x0a, _32, true }, + { 0x0a, _32, 0x0b, _32, true }, + { 0x0a, _32, 0x0c, _32, false }, + + { 0x0b, _32, 0x04, _32, false }, + { 0x0b, _32, 0x05, _32, true }, + { 0x0b, _32, 0x06, _32, true }, + { 0x0b, _32, 0x07, _32, true }, + { 0x0b, _32, 0x08, _32, true }, + { 0x0b, _32, 0x09, _32, true }, + { 0x0b, _32, 0x0a, _32, true }, + { 0x0b, _32, 0x0b, _32, true }, + { 0x0b, _32, 0x0c, _32, false }, + + { 0x0d, _32, 0x08, _32, false }, + { 0x0d, _32, 0x09, _32, true }, + { 0x0d, _32, 0x0a, _32, true }, + { 0x0d, _32, 0x0b, _32, true }, + { 0x0d, _32, 0x0c, _32, true }, + { 0x0d, _32, 0x0d, _32, true }, + { 0x0d, _32, 0x0e, _32, true }, + { 0x0d, _32, 0x0f, _32, true }, + { 0x0d, _32, 0x10, _32, false }, + + { 0x0e, _32, 0x08, _32, false }, + { 0x0e, _32, 0x09, _32, true }, + { 0x0e, _32, 0x0a, _32, true }, + { 0x0e, _32, 0x0b, _32, true }, + { 0x0e, _32, 0x0c, _32, true }, + { 0x0e, _32, 0x0d, _32, true }, + { 0x0e, _32, 0x0e, _32, true }, + { 0x0e, _32, 0x0f, _32, true }, + { 0x0e, _32, 0x10, _32, false }, + + { 0x0f, _32, 0x08, _32, false }, + { 0x0f, _32, 0x09, _32, true }, + { 0x0f, _32, 0x0a, _32, true }, + { 0x0f, _32, 0x0b, _32, true }, + { 0x0f, _32, 0x0c, _32, true }, + { 0x0f, _32, 0x0d, _32, true }, + { 0x0f, _32, 0x0e, _32, true }, + { 0x0f, _32, 0x0f, _32, true }, + { 0x0f, _32, 0x10, _32, false }, +}; + +static void enable_debug_extensions(void) +{ + unsigned long cr4 =3D read_cr4(); + + if ( !(cr4 & X86_CR4_DE) ) + write_cr4(cr4 | X86_CR4_DE); +} + +static void init_breakpoint(enum width width) +{ + unsigned long io0, dr7; + + switch (width) + { + case _16: + io0 =3D DR7_SYM(0, G, IO, 16) | X86_DR7_GE | X86_DR7_DEFAULT; + break; + case _32: + io0 =3D DR7_SYM(0, G, IO, 32) | X86_DR7_GE | X86_DR7_DEFAULT; + break; + default: + xtf_failure(" Fail: Unknown width %d\n", width); + return; + } + + write_dr7(io0); + + if ( (dr7 =3D read_dr7()) !=3D io0 ) + xtf_failure(" Fail: dr7 %#lx !=3D io0 %#lx\n", dr7, io0); +} + +static void set_breakpoint(unsigned long io_port) +{ + unsigned long dr0; + + write_dr0(io_port); + + if ( (dr0 =3D read_dr0()) !=3D io_port ) + xtf_failure(" Fail: dr0 %#lx !=3D %#lx\n", dr0, io_port); +} + +/* Set vCPU IOPL to 1 to allow IO calls in kernel space */ +static void set_iopl(void) +{ + unsigned int iopl =3D 1; + + hypercall_physdev_op(PHYSDEVOP_set_iopl, &iopl); +} + +static exinfo_t io_op(uint16_t io_port, enum width io_op_len) +{ + exinfo_t fault =3D 0; + + switch (io_op_len) + { + case _16: + asm volatile ("outw %w0, %w1; 1:" + _ASM_EXTABLE_HANDLER(1b, 1b, %P[rec]) + : "+a" (fault) + : "Nd" (io_port), + [rec] "p" (ex_record_fault_eax)); + break; + case _32: + asm volatile ("outl %k0, %w1; 1:" + _ASM_EXTABLE_HANDLER(1b, 1b, %P[rec]) + : "+a" (fault) + : "Nd" (io_port), + [rec] "p" (ex_record_fault_eax)); + break; + default: + xtf_failure(" Fail: Unknown width %d\n", io_op_len); + break; + } + + return fault; +} + +void test_main(void) +{ + unsigned int i; + + enable_debug_extensions(); + set_iopl(); + + for ( i =3D 0; i < ARRAY_SIZE(tests); ++i ) + { + const struct test *t =3D &tests[i]; + + /* arrange */ + init_breakpoint(t->breakpoint_size); + set_breakpoint(t->breakpoint_port); + + /* act */ + exinfo_t ex =3D io_op(t->io_op_port, t->io_op_len); + + /* assert */ + if ( t->expect_breakpoint_trigger && ex !=3D EXINFO_SYM(DB, 0) ) + xtf_failure("Fail: Expected trigger with breakpoint port 0x%02= lx and io port 0x%02x, but got no trigger.\n", t->breakpoint_port, t->io_op= _port); + if ( !t->expect_breakpoint_trigger && ex =3D=3D EXINFO_SYM(DB, 0) ) + xtf_failure("Fail: Expected no trigger with breakpoint port 0x= %02lx and io port 0x%02x, but got trigger.\n", t->breakpoint_port, t->io_op= _port); + } + + xtf_success(NULL); +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ --=20 2.34.1