From nobody Fri Mar 29 01:45:33 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 80.81.252.135 is neither permitted nor denied by domain of seabios.org) client-ip=80.81.252.135; envelope-from=seabios-bounces@seabios.org; helo=mail.coreboot.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zoho.com: 80.81.252.135 is neither permitted nor denied by domain of seabios.org) smtp.mailfrom=seabios-bounces@seabios.org; dmarc=fail(p=none dis=none) header.from=yandex-team.ru Return-Path: Received: from mail.coreboot.org (mail.coreboot.org [80.81.252.135]) by mx.zohomail.com with SMTPS id 1544622366391545.275580425163; Wed, 12 Dec 2018 05:46:06 -0800 (PST) Received: from [127.0.0.1] (helo=ra.coreboot.org) by mail.coreboot.org with esmtp (Exim 4.88) (envelope-from ) id 1gX4oL-0001vs-39; Wed, 12 Dec 2018 14:44:25 +0100 Received: from forwardcorp1o.cmail.yandex.net ([37.9.109.47]) by mail.coreboot.org with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.88) (envelope-from ) id 1gX4o7-0001vS-35 for seabios@seabios.org; Wed, 12 Dec 2018 14:44:24 +0100 Received: from mxbackcorp2j.mail.yandex.net (mxbackcorp2j.mail.yandex.net [IPv6:2a02:6b8:0:1619::119]) by forwardcorp1o.cmail.yandex.net (Yandex) with ESMTP id 50FDE20F63; Wed, 12 Dec 2018 16:45:15 +0300 (MSK) Received: from smtpcorp1o.mail.yandex.net (smtpcorp1o.mail.yandex.net [2a02:6b8:0:1a2d::30]) by mxbackcorp2j.mail.yandex.net (nwsmtp/Yandex) with ESMTP id HJ71rKqJvQ-jFUqpe1U; Wed, 12 Dec 2018 16:45:15 +0300 Received: from dynamic-red.dhcp.yndx.net (dynamic-red.dhcp.yndx.net [2a02:6b8:0:40c:f68c:50ff:fee9:44bd]) by smtpcorp1o.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id gOQNkVDFkJ-jEB4Ob3m; Wed, 12 Dec 2018 16:45:15 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1544622315; bh=Bp6+gUi/KQw81d/DTASscyv2R4LPVCdvuwTFPzZZ0c8=; h=From:To:Cc:Subject:Date:Message-Id; b=nds2ubUHr1wD9zUpa31QIK1hyTqZGTRKytjcVdWDdGPkmHHT1jv3vDme5hvmnZj8Q lAZLkusVGEq9J5LwR7zH8HnlDAxQYt6gkp3LhVunHVSf1HGrlBRpupNSVt+iDmiIfa j1UvthMvurzB5OJCQ1AVHXHJ8l0hrYAmro00IbfA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1544622315; bh=Bp6+gUi/KQw81d/DTASscyv2R4LPVCdvuwTFPzZZ0c8=; h=From:To:Cc:Subject:Date:Message-Id; b=nds2ubUHr1wD9zUpa31QIK1hyTqZGTRKytjcVdWDdGPkmHHT1jv3vDme5hvmnZj8Q lAZLkusVGEq9J5LwR7zH8HnlDAxQYt6gkp3LhVunHVSf1HGrlBRpupNSVt+iDmiIfa j1UvthMvurzB5OJCQ1AVHXHJ8l0hrYAmro00IbfA= Authentication-Results: smtpcorp1o.mail.yandex.net; dkim=pass header.i=@yandex-team.ru From: Evgeny Yakovlev To: seabios@seabios.org Date: Wed, 12 Dec 2018 16:45:08 +0300 Message-Id: <1544622308-29067-1-git-send-email-wrfsh@yandex-team.ru> X-Mailer: git-send-email 2.7.4 X-Spam-Score: -2.6 (--) Subject: [SeaBIOS] [PATCH] shadow: set code segment to high rom region when enabling RAM X-BeenThere: seabios@seabios.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SeaBIOS mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: seabios-bounces@seabios.org Sender: "SeaBIOS" X-Duff: Orig. Duff, Duff Lite, Duff Dry, Duff Dark, Raspberry Duff, Lady Duff, Red Duff, Tartar Control Duff X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Currently make_bios_writable_intel will call __make_bios_writeable_intel from high rom memory by manually correcting its offset to make sure that we safely execute it while overriding memory mapping through PAMs However we still may call code from low memory, when __make_bios_writeable_intel itself calls other code without manual pointer adjustments. Right now it calls pci_config_readl and pci_config_writel. Consider this scenario: 0. Linker puts pci_config_writel in F-segment. 1. first pci_config_writel is called to reprogram PAM0-3, which means remap regions 0xF0000-0xFFFFF and 0xD0000 - 0xC7FFF. 2. second pci_config_writel is called to reprogram PAM4-7 but code in F-segment is no longer valid, including pci_config_writel. However we don't crash due to instruction cache being hot between two calls. Adding manual i-cache flush (by reloading the same CS segment for example) between two calls finally crashes the firmware. This change wraps a call to __make_bios_writable_bios by setting code segment at base 0xFFF00000. This way simple nested function calls work as long as no data fetches happen during execution through CS segment (i.e. something like dprintf is still not safe to call). Signed-off-by: Evgeny Yakovlev --- src/config.h | 16 ++++++++++------ src/fw/shadow.c | 37 ++++++++++++++++++++++++++++--------- src/misc.c | 8 ++++++++ 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/config.h b/src/config.h index 93c8dbc..87c4118 100644 --- a/src/config.h +++ b/src/config.h @@ -60,13 +60,17 @@ #define SEG_BDA 0x0040 #define SEG_BIOS 0xf000 =20 +// On the emulators, the bios at 0xf0000 is also at 0xffff0000 +#define BIOS_SRC_OFFSET 0xfff00000 + // Segment definitions in protected mode (see rombios32_gdt in misc.c) -#define SEG32_MODE32_CS (1 << 3) -#define SEG32_MODE32_DS (2 << 3) -#define SEG32_MODE16_CS (3 << 3) -#define SEG32_MODE16_DS (4 << 3) -#define SEG32_MODE16BIG_CS (5 << 3) -#define SEG32_MODE16BIG_DS (6 << 3) +#define SEG32_MODE32_CS (1 << 3) +#define SEG32_MODE32_DS (2 << 3) +#define SEG32_MODE16_CS (3 << 3) +#define SEG32_MODE16_DS (4 << 3) +#define SEG32_MODE16BIG_CS (5 << 3) +#define SEG32_MODE16BIG_DS (6 << 3) +#define SEG32_MODE32_HIGH_CS (7 << 3) =20 // Debugging levels. If non-zero and CONFIG_DEBUG_LEVEL is greater // than the specified value, then the corresponding irq handler will diff --git a/src/fw/shadow.c b/src/fw/shadow.c index 4c627a8..80d0889 100644 --- a/src/fw/shadow.c +++ b/src/fw/shadow.c @@ -18,9 +18,6 @@ #include "util.h" // make_bios_writable #include "x86.h" // wbinvd =20 -// On the emulators, the bios at 0xf0000 is also at 0xffff0000 -#define BIOS_SRC_OFFSET 0xfff00000 - union pamdata_u { u8 data8[8]; u32 data32[2]; @@ -56,6 +53,30 @@ __make_bios_writable_intel(u16 bdf, u32 pam0) , SYMBOL(code32flat_end) - SYMBOL(code32flat_start)); } =20 +// A wrapper for executing __make_bios_writable_intel in high memory code = segment +static void +__make_bios_writable_intel_highmem(u16 bdf, u32 pam0) +{ + // Save whatever CS segment we've had before entering here + // and switch to highmem code + u16 prev_cs; + __asm__ __volatile__ ("mov %%cs, %0":"=3Drm"(prev_cs)); + __asm__ __volatile__ ("ljmp %0, $__make_bios_writable_intel_highmem__e= nter\n" + "__make_bios_writable_intel_highmem__enter:\n" + : + : "n"(SEG32_MODE32_HIGH_CS)); + + __make_bios_writable_intel(bdf, pam0); + + // Far jump to return to previous segment + __asm__ __volatile__ ("push %0\n" + "push $__make_bios_writable_intel_highmem__exit\= n" + "retf\n" + "__make_bios_writable_intel_highmem__exit:\n" + : + : "rm"((u32)prev_cs)); +} + static void make_bios_writable_intel(u16 bdf, u32 pam0) { @@ -65,13 +86,11 @@ make_bios_writable_intel(u16 bdf, u32 pam0) // if ram isn't backing the bios segment when shadowing is // disabled, the code itself won't be in memory. So, run the // code from the high-memory flash location. - u32 pos =3D (u32)__make_bios_writable_intel + BIOS_SRC_OFFSET; - void (*func)(u16 bdf, u32 pam0) =3D (void*)pos; - func(bdf, pam0); - return; + __make_bios_writable_intel_highmem(bdf, pam0); + } else { + // Ram already present - just enable writes + __make_bios_writable_intel(bdf, pam0); } - // Ram already present - just enable writes - __make_bios_writable_intel(bdf, pam0); } =20 static void diff --git a/src/misc.c b/src/misc.c index b511730..cb931a5 100644 --- a/src/misc.c +++ b/src/misc.c @@ -160,6 +160,14 @@ u64 rombios32_gdt[] VARFSEG __aligned(8) =3D { GDT_GRANLIMIT(0xffffffff) | GDT_CODE | GDT_BASE(BUILD_BIOS_ADDR), // 16 bit data segment base=3D0 limit=3D0xffffffff (SEG32_MODE16BIG_DS) GDT_GRANLIMIT(0xffffffff) | GDT_DATA, + + // + // Following segments are used when enabling shadow memory + // where we need to execute code strictly from base 0xFFF00000 + // + + // 32 bit code segment in high memory + GDT_GRANLIMIT(0xfffff) | GDT_CODE | GDT_B | GDT_BASE(BIOS_SRC_OFFSET), }; =20 // GDT descriptor --=20 2.7.4 _______________________________________________ SeaBIOS mailing list SeaBIOS@seabios.org https://mail.coreboot.org/mailman/listinfo/seabios