From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Sasha Levin <sashal@kernel.org>,
dri-devel@lists.freedesktop.org,
kernel test robot <lkp@intel.com>,
Thomas Zimmermann <tzimmermann@suse.de>
Subject: [PATCH AUTOSEL 5.13 004/189] drm/ast: Fixed CVE for DP501
Date: Tue, 6 Jul 2021 07:11:04 -0400 [thread overview]
Message-ID: <20210706111409.2058071-4-sashal@kernel.org> (raw)
In-Reply-To: <20210706111409.2058071-1-sashal@kernel.org>
From: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
[ Upstream commit ba4e0339a6a33e2ba341703ce14ae8ca203cb2f1 ]
[Bug][DP501]
If ASPEED P2A (PCI to AHB) bridge is disabled and disallowed for
CVE_2019_6260 item3, and then the monitor's EDID is unable read through
Parade DP501.
The reason is the DP501's FW is mapped to BMC addressing space rather
than Host addressing space.
The resolution is that using "pci_iomap_range()" maps to DP501's FW that
stored on the end of FB (Frame Buffer).
In this case, FrameBuffer reserves the last 2MB used for the image of
DP501.
Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20210421085859.17761-1-kuohsiang_chou@aspeedtech.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/ast/ast_dp501.c | 139 +++++++++++++++++++++++---------
drivers/gpu/drm/ast/ast_drv.h | 12 +++
drivers/gpu/drm/ast/ast_main.c | 11 ++-
3 files changed, 125 insertions(+), 37 deletions(-)
diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c
index 88121c0e0d05..cd93c44f2662 100644
--- a/drivers/gpu/drm/ast/ast_dp501.c
+++ b/drivers/gpu/drm/ast/ast_dp501.c
@@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size)
u32 i, data;
u32 boot_address;
+ if (ast->config_mode != ast_use_p2a)
+ return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (data) {
boot_address = get_fw_base(ast);
@@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev)
u8 *fw_addr = NULL;
u8 jreg;
+ if (ast->config_mode != ast_use_p2a)
+ return false;
+
data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
if (!data) {
@@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev)
struct ast_private *ast = to_ast_private(dev);
u32 boot_address, offset, data;
u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
+ u32 *plinkcap;
- boot_address = get_fw_base(ast);
-
- /* validate FW version */
- offset = 0xf000;
- data = ast_mindwm(ast, boot_address + offset);
- if ((data & 0xf0) != 0x10) /* version: 1x */
- return maxclk;
-
- /* Read Link Capability */
- offset = 0xf014;
- *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
- if (linkcap[2] == 0) {
- linkrate = linkcap[0];
- linklanes = linkcap[1];
- data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
- if (data > 0xff)
- data = 0xff;
- maxclk = (u8)data;
+ if (ast->config_mode == ast_use_p2a) {
+ boot_address = get_fw_base(ast);
+
+ /* validate FW version */
+ offset = AST_DP501_GBL_VERSION;
+ data = ast_mindwm(ast, boot_address + offset);
+ if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */
+ return maxclk;
+
+ /* Read Link Capability */
+ offset = AST_DP501_LINKRATE;
+ plinkcap = (u32 *)linkcap;
+ *plinkcap = ast_mindwm(ast, boot_address + offset);
+ if (linkcap[2] == 0) {
+ linkrate = linkcap[0];
+ linklanes = linkcap[1];
+ data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
+ if (data > 0xff)
+ data = 0xff;
+ maxclk = (u8)data;
+ }
+ } else {
+ if (!ast->dp501_fw_buf)
+ return AST_DP501_DEFAULT_DCLK; /* 1024x768 as default */
+
+ /* dummy read */
+ offset = 0x0000;
+ data = readl(ast->dp501_fw_buf + offset);
+
+ /* validate FW version */
+ offset = AST_DP501_GBL_VERSION;
+ data = readl(ast->dp501_fw_buf + offset);
+ if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */
+ return maxclk;
+
+ /* Read Link Capability */
+ offset = AST_DP501_LINKRATE;
+ plinkcap = (u32 *)linkcap;
+ *plinkcap = readl(ast->dp501_fw_buf + offset);
+ if (linkcap[2] == 0) {
+ linkrate = linkcap[0];
+ linklanes = linkcap[1];
+ data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
+ if (data > 0xff)
+ data = 0xff;
+ maxclk = (u8)data;
+ }
}
return maxclk;
}
@@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata)
{
struct ast_private *ast = to_ast_private(dev);
u32 i, boot_address, offset, data;
+ u32 *pEDIDidx;
- boot_address = get_fw_base(ast);
-
- /* validate FW version */
- offset = 0xf000;
- data = ast_mindwm(ast, boot_address + offset);
- if ((data & 0xf0) != 0x10)
- return false;
-
- /* validate PnP Monitor */
- offset = 0xf010;
- data = ast_mindwm(ast, boot_address + offset);
- if (!(data & 0x01))
- return false;
+ if (ast->config_mode == ast_use_p2a) {
+ boot_address = get_fw_base(ast);
- /* Read EDID */
- offset = 0xf020;
- for (i = 0; i < 128; i += 4) {
- data = ast_mindwm(ast, boot_address + offset + i);
- *(u32 *)(ediddata + i) = data;
+ /* validate FW version */
+ offset = AST_DP501_GBL_VERSION;
+ data = ast_mindwm(ast, boot_address + offset);
+ if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
+ return false;
+
+ /* validate PnP Monitor */
+ offset = AST_DP501_PNPMONITOR;
+ data = ast_mindwm(ast, boot_address + offset);
+ if (!(data & AST_DP501_PNP_CONNECTED))
+ return false;
+
+ /* Read EDID */
+ offset = AST_DP501_EDID_DATA;
+ for (i = 0; i < 128; i += 4) {
+ data = ast_mindwm(ast, boot_address + offset + i);
+ pEDIDidx = (u32 *)(ediddata + i);
+ *pEDIDidx = data;
+ }
+ } else {
+ if (!ast->dp501_fw_buf)
+ return false;
+
+ /* dummy read */
+ offset = 0x0000;
+ data = readl(ast->dp501_fw_buf + offset);
+
+ /* validate FW version */
+ offset = AST_DP501_GBL_VERSION;
+ data = readl(ast->dp501_fw_buf + offset);
+ if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
+ return false;
+
+ /* validate PnP Monitor */
+ offset = AST_DP501_PNPMONITOR;
+ data = readl(ast->dp501_fw_buf + offset);
+ if (!(data & AST_DP501_PNP_CONNECTED))
+ return false;
+
+ /* Read EDID */
+ offset = AST_DP501_EDID_DATA;
+ for (i = 0; i < 128; i += 4) {
+ data = readl(ast->dp501_fw_buf + offset + i);
+ pEDIDidx = (u32 *)(ediddata + i);
+ *pEDIDidx = data;
+ }
}
return true;
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index e82ab8628770..911f9f414774 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -150,6 +150,7 @@ struct ast_private {
void __iomem *regs;
void __iomem *ioregs;
+ void __iomem *dp501_fw_buf;
enum ast_chip chip;
bool vga2_clone;
@@ -325,6 +326,17 @@ int ast_mode_config_init(struct ast_private *ast);
#define AST_MM_ALIGN_SHIFT 4
#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
+#define AST_DP501_FW_VERSION_MASK GENMASK(7, 4)
+#define AST_DP501_FW_VERSION_1 BIT(4)
+#define AST_DP501_PNP_CONNECTED BIT(1)
+
+#define AST_DP501_DEFAULT_DCLK 65
+
+#define AST_DP501_GBL_VERSION 0xf000
+#define AST_DP501_PNPMONITOR 0xf010
+#define AST_DP501_LINKRATE 0xf014
+#define AST_DP501_EDID_DATA 0xf020
+
int ast_mm_init(struct ast_private *ast);
/* ast post */
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 0ac3c2039c4b..3976a258799f 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -99,7 +99,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
/* Double check it's actually working */
data = ast_read32(ast, 0xf004);
- if (data != 0xFFFFFFFF) {
+ if ((data != 0xFFFFFFFF) && (data != 0x00)) {
/* P2A works, grab silicon revision */
ast->config_mode = ast_use_p2a;
@@ -411,6 +411,7 @@ struct ast_private *ast_device_create(const struct drm_driver *drv,
return ast;
dev = &ast->base;
+ dev->pdev = pdev;
pci_set_drvdata(pdev, dev);
ast->regs = pci_iomap(pdev, 1, 0);
@@ -450,6 +451,14 @@ struct ast_private *ast_device_create(const struct drm_driver *drv,
if (ret)
return ERR_PTR(ret);
+ /* map reserved buffer */
+ ast->dp501_fw_buf = NULL;
+ if (dev->vram_mm->vram_size < pci_resource_len(dev->pdev, 0)) {
+ ast->dp501_fw_buf = pci_iomap_range(dev->pdev, 0, dev->vram_mm->vram_size, 0);
+ if (!ast->dp501_fw_buf)
+ drm_info(dev, "failed to map reserved buffer!\n");
+ }
+
ret = ast_mode_config_init(ast);
if (ret)
return ERR_PTR(ret);
--
2.30.2
next prev parent reply other threads:[~2021-07-06 11:14 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-06 11:11 [PATCH AUTOSEL 5.13 001/189] drm/etnaviv: fix NULL check before some freeing functions is not needed Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 002/189] drm/mxsfb: Don't select DRM_KMS_FB_HELPER Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 003/189] drm/zte: " Sasha Levin
2021-07-06 11:11 ` Sasha Levin [this message]
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 005/189] drm/amd/display: fix HDCP reset sequence on reinitialize Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 006/189] drm/amd/display: Revert wait vblank on update dpp clock Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 007/189] drm/amd/display: Fix BSOD with NULL check Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 008/189] drm/amd/amdgpu/sriov disable all ip hw status by default Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 009/189] drm/vc4: fix argument ordering in vc4_crtc_get_margins() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 010/189] drm/bridge: nwl-dsi: Force a full modeset when crtc_state->active is changed to be true Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 011/189] drm/imx: ipuv3-plane: do not advertise YUV formats on planes without CSC Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 012/189] drm/imx: Add 8 pixel alignment fix Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 014/189] drm/amd/display: fix potential gpu reset deadlock Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 015/189] drm/amdgpu: change the default timeout for kernel compute queues Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 016/189] drm/amd/display: Fix clock table filling logic Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 017/189] drm/amd/display: fix use_max_lb flag for 420 pixel formats Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 025/189] drm/mediatek: Fix PM reference leak in mtk_crtc_ddp_hw_init() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 026/189] drm/panfrost: devfreq: Disable devfreq when num_supplies > 1 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 028/189] drm/bridge: lt9611: Add missing MODULE_DEVICE_TABLE Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 030/189] drm/virtio: Fixes a potential NULL pointer dereference on probe failure Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 031/189] drm/virtio: Fix double free " Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 037/189] drm/amdgpu/display: restore the backlight on modeset (v2) Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 038/189] drm/scheduler: Fix hang when sched_entity released Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 039/189] drm/sched: Avoid data corruptions Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 042/189] drm/amd/pm: fix return value in aldebaran_set_mp1_state() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 043/189] drm/vc4: Fix clock source for VEC PixelValve on BCM2711 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 044/189] drm/vc4: hdmi: Fix PM reference leak in vc4_hdmi_encoder_pre_crtc_co() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 048/189] drm/bridge: cdns: Fix PM reference leak in cdns_dsi_transfer() Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 050/189] drm/amd/display: fix odm scaling Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 051/189] drm/amdgpu/swsmu/aldebaran: fix check in is_dpm_running Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 054/189] drm: rockchip: add missing registers for RK3188 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 055/189] drm: rockchip: add missing registers for RK3066 Sasha Levin
2021-07-06 11:11 ` [PATCH AUTOSEL 5.13 058/189] drm/tegra: hub: Fix YUV support Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 061/189] drm: bridge: cdns-mhdp8546: Fix PM reference leak in Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 066/189] drm/amdgpu: fix metadata_size for ubo ioctl queries Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 067/189] drm/amdgpu: fix sdma firmware version error in sriov Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 068/189] drm/amd/display: Avoid HDCP over-read and corruption Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 069/189] drm/amdgpu: remove unsafe optimization to drop preamble ib Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 088/189] drm/amd/display: Fix DCN 3.01 DSCCLK validation Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 089/189] drm/amd/display: Revert "Fix clock table filling logic" Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 090/189] drm/amd/display: Update scaling settings on modeset Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 091/189] drm/amd/display: Release MST resources on switch from MST to SST Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 092/189] drm/amd/display: Set DISPCLK_MAX_ERRDET_CYCLES to 7 Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 093/189] drm/amd/display: Fix off-by-one error in DML Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 094/189] drm/amd/display: Fix crash during MPO + ODM combine mode recalculation Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 098/189] drm/amdkfd: use allowed domain for vmbo validation Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 103/189] drm/amd/display: Verify Gamma & Degamma LUT sizes in amdgpu_dm_atomic_check Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 111/189] drm/amdkfd: fix circular locking on get_wave_state Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 112/189] drm/amd/display: Cover edge-case when changing DISPCLK WDIVIDER Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 113/189] drm/amdgpu/gfx9: fix the doorbell missing when in CGPG issue Sasha Levin
2021-07-06 21:44 ` Alex Deucher
2021-07-06 23:09 ` Felix Kuehling
2021-07-07 10:46 ` Sasha Levin
2021-07-06 11:12 ` [PATCH AUTOSEL 5.13 114/189] drm/amdkfd: Fix circular lock in nocpsch path Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 128/189] drm/amdgpu: fix bad address translation for sienna_cichlid Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 129/189] drm/amdkfd: Walk through list with dqm lock hold Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 146/189] Revert "drm/amdgpu/gfx9: fix the doorbell missing when in CGPG issue." Sasha Levin
2021-07-06 11:13 ` [PATCH AUTOSEL 5.13 147/189] drm/amd/display: Fix edp_bootup_bl_level initialization issue Sasha Levin
2021-07-07 10:52 ` [PATCH AUTOSEL 5.13 001/189] drm/etnaviv: fix NULL check before some freeing functions is not needed Lucas Stach
2021-07-07 11:50 ` Christian König
2021-07-14 16:45 ` Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210706111409.2058071-4-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lkp@intel.com \
--cc=stable@vger.kernel.org \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox