From: Andrew Scull <ascull@google.com>
To: u-boot@lists.denx.de
Cc: sjg@chromium.org, bmeng.cn@gmail.com, trini@konsulko.com,
Andrew Scull <ascull@google.com>
Subject: [PATCH v3 10/18] pci: Range check address conversions
Date: Thu, 21 Apr 2022 16:11:08 +0000 [thread overview]
Message-ID: <20220421161116.1202023-11-ascull@google.com> (raw)
In-Reply-To: <20220421161116.1202023-1-ascull@google.com>
When converting between PCI bus and physical addresses, include a length
parameter that can be used to check that the entire range fits within
one of the PCI regions. This prevents an address being returned that
might be only partially valid for the range it is going to be used for.
Where the range check is not wanted, passing a length of 0 will have the
same behaviour as before this change.
Signed-off-by: Andrew Scull <ascull@google.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---
drivers/pci/pci-uclass.c | 57 ++++++++++++++++++++++++----------------
include/pci.h | 20 +++++++-------
2 files changed, 46 insertions(+), 31 deletions(-)
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 0424cd339e..997ca0d5e4 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -1390,12 +1390,13 @@ void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr)
dm_pci_write_config32(dev, bar, addr);
}
-static int _dm_pci_bus_to_phys(struct udevice *ctlr,
- pci_addr_t bus_addr, unsigned long flags,
+static int _dm_pci_bus_to_phys(struct udevice *ctlr, pci_addr_t bus_addr,
+ size_t len, unsigned long flags,
unsigned long skip_mask, phys_addr_t *pa)
{
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
struct pci_region *res;
+ pci_addr_t offset;
int i;
if (hose->region_count == 0) {
@@ -1412,18 +1413,25 @@ static int _dm_pci_bus_to_phys(struct udevice *ctlr,
if (res->flags & skip_mask)
continue;
- if (bus_addr >= res->bus_start &&
- (bus_addr - res->bus_start) < res->size) {
- *pa = (bus_addr - res->bus_start + res->phys_start);
- return 0;
- }
+ if (bus_addr < res->bus_start)
+ continue;
+
+ offset = bus_addr - res->bus_start;
+ if (offset >= res->size)
+ continue;
+
+ if (len > res->size - offset)
+ continue;
+
+ *pa = res->phys_start + offset;
+ return 0;
}
return 1;
}
phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
- unsigned long flags)
+ size_t len, unsigned long flags)
{
phys_addr_t phys_addr = 0;
struct udevice *ctlr;
@@ -1437,14 +1445,14 @@ phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
* on matches that don't have PCI_REGION_SYS_MEMORY set
*/
if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
- ret = _dm_pci_bus_to_phys(ctlr, bus_addr,
+ ret = _dm_pci_bus_to_phys(ctlr, bus_addr, len,
flags, PCI_REGION_SYS_MEMORY,
&phys_addr);
if (!ret)
return phys_addr;
}
- ret = _dm_pci_bus_to_phys(ctlr, bus_addr, flags, 0, &phys_addr);
+ ret = _dm_pci_bus_to_phys(ctlr, bus_addr, len, flags, 0, &phys_addr);
if (ret)
puts("pci_hose_bus_to_phys: invalid physical address\n");
@@ -1453,12 +1461,12 @@ phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t bus_addr,
}
static int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
- unsigned long flags, unsigned long skip_mask,
- pci_addr_t *ba)
+ size_t len, unsigned long flags,
+ unsigned long skip_mask, pci_addr_t *ba)
{
struct pci_region *res;
struct udevice *ctlr;
- pci_addr_t bus_addr;
+ phys_addr_t offset;
int i;
struct pci_controller *hose;
@@ -1480,20 +1488,25 @@ static int _dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
if (res->flags & skip_mask)
continue;
- bus_addr = phys_addr - res->phys_start + res->bus_start;
+ if (phys_addr < res->phys_start)
+ continue;
- if (bus_addr >= res->bus_start &&
- (bus_addr - res->bus_start) < res->size) {
- *ba = bus_addr;
- return 0;
- }
+ offset = phys_addr - res->phys_start;
+ if (offset >= res->size)
+ continue;
+
+ if (len > res->size - offset)
+ continue;
+
+ *ba = res->bus_start + offset;
+ return 0;
}
return 1;
}
pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
- unsigned long flags)
+ size_t len, unsigned long flags)
{
pci_addr_t bus_addr = 0;
int ret;
@@ -1503,13 +1516,13 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t phys_addr,
* on matches that don't have PCI_REGION_SYS_MEMORY set
*/
if ((flags & PCI_REGION_TYPE) == PCI_REGION_MEM) {
- ret = _dm_pci_phys_to_bus(dev, phys_addr, flags,
+ ret = _dm_pci_phys_to_bus(dev, phys_addr, len, flags,
PCI_REGION_SYS_MEMORY, &bus_addr);
if (!ret)
return bus_addr;
}
- ret = _dm_pci_phys_to_bus(dev, phys_addr, flags, 0, &bus_addr);
+ ret = _dm_pci_phys_to_bus(dev, phys_addr, len, flags, 0, &bus_addr);
if (ret)
puts("pci_hose_phys_to_bus: invalid physical address\n");
diff --git a/include/pci.h b/include/pci.h
index 3d0356b8fd..966b84c148 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -1313,14 +1313,15 @@ void dm_pci_write_bar32(struct udevice *dev, int barnum, u32 addr);
u32 dm_pci_read_bar32(const struct udevice *dev, int barnum);
/**
- * dm_pci_bus_to_phys() - convert a PCI bus address to a physical address
+ * dm_pci_bus_to_phys() - convert a PCI bus address range to a physical address
*
* @dev: Device containing the PCI address
* @addr: PCI address to convert
+ * @len: Length of the address range
* @flags: Flags for the region type (PCI_REGION_...)
* Return: physical address corresponding to that PCI bus address
*/
-phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t addr,
+phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t addr, size_t len,
unsigned long flags);
/**
@@ -1328,10 +1329,11 @@ phys_addr_t dm_pci_bus_to_phys(struct udevice *dev, pci_addr_t addr,
*
* @dev: Device containing the bus address
* @addr: Physical address to convert
+ * @len: Length of the address range
* @flags: Flags for the region type (PCI_REGION_...)
* Return: PCI bus address corresponding to that physical address
*/
-pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr,
+pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr, size_t len,
unsigned long flags);
/**
@@ -1453,19 +1455,19 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap);
int dm_pci_flr(struct udevice *dev);
#define dm_pci_virt_to_bus(dev, addr, flags) \
- dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), (flags))
+ dm_pci_phys_to_bus(dev, (virt_to_phys(addr)), 0, (flags))
#define dm_pci_bus_to_virt(dev, addr, flags, len, map_flags) \
- map_physmem(dm_pci_bus_to_phys(dev, (addr), (flags)), \
+ map_physmem(dm_pci_bus_to_phys(dev, (addr), (len), (flags)), \
(len), (map_flags))
#define dm_pci_phys_to_mem(dev, addr) \
- dm_pci_phys_to_bus((dev), (addr), PCI_REGION_MEM)
+ dm_pci_phys_to_bus((dev), (addr), 0, PCI_REGION_MEM)
#define dm_pci_mem_to_phys(dev, addr) \
- dm_pci_bus_to_phys((dev), (addr), PCI_REGION_MEM)
+ dm_pci_bus_to_phys((dev), (addr), 0, PCI_REGION_MEM)
#define dm_pci_phys_to_io(dev, addr) \
- dm_pci_phys_to_bus((dev), (addr), PCI_REGION_IO)
+ dm_pci_phys_to_bus((dev), (addr), 0, PCI_REGION_IO)
#define dm_pci_io_to_phys(dev, addr) \
- dm_pci_bus_to_phys((dev), (addr), PCI_REGION_IO)
+ dm_pci_bus_to_phys((dev), (addr), 0, PCI_REGION_IO)
#define dm_pci_virt_to_mem(dev, addr) \
dm_pci_virt_to_bus((dev), (addr), PCI_REGION_MEM)
--
2.36.0.rc2.479.g8af0fa9b8e-goog
next prev parent reply other threads:[~2022-04-21 16:13 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-21 16:10 [PATCH v3 00/18] virtio: pci: Add and fix consistency checks Andrew Scull
2022-04-21 16:10 ` [PATCH v3 01/18] virtio: pci: Allow exclusion of legacy driver Andrew Scull
2022-05-03 23:10 ` Tom Rini
2022-04-21 16:11 ` [PATCH v3 02/18] virtio: pci: Fix discovery of device config length Andrew Scull
2022-04-21 16:11 ` [PATCH v3 03/18] virtio: pci: Bounds check device config access Andrew Scull
2022-04-21 16:11 ` [PATCH v3 04/18] virtio: pci: Bounds check notification writes Andrew Scull
2022-04-21 16:11 ` [PATCH v3 05/18] virtio: pci: Check virtio common config size Andrew Scull
2022-04-21 16:11 ` [PATCH v3 06/18] virtio: pci: Check virtio capability is in bounds Andrew Scull
2022-04-21 16:11 ` [PATCH v3 07/18] virtio: pci: Read entire capability into memory Andrew Scull
2022-04-21 16:11 ` [PATCH v3 08/18] pci: Fix use of flags in dm_pci_map_bar() Andrew Scull
2022-04-22 6:37 ` Bin Meng
2022-04-21 16:11 ` [PATCH v3 09/18] pci: Check region ranges are addressable Andrew Scull
2022-04-21 16:11 ` Andrew Scull [this message]
2022-04-21 16:11 ` [PATCH v3 11/18] test: pci: Test PCI address conversion functions Andrew Scull
2022-04-22 6:50 ` Bin Meng
2022-04-21 16:11 ` [PATCH v3 12/18] pci: Map bars with offset and length Andrew Scull
2022-04-22 6:52 ` Bin Meng
2022-04-21 16:11 ` [PATCH v3 13/18] pci: Match region flags using a mask Andrew Scull
2022-04-21 16:11 ` [PATCH v3 14/18] pci: Update dm_pci_bus_to_virt() parameters Andrew Scull
2022-04-22 7:38 ` Bin Meng
2022-04-21 16:11 ` [PATCH v3 15/18] pci: Add mask parameter to dm_pci_map_bar() Andrew Scull
2022-04-22 7:39 ` Bin Meng
2022-04-21 16:11 ` [PATCH v3 16/18] virtio: pci: Check virtio configs are mapped Andrew Scull
2022-04-21 16:11 ` [PATCH v3 17/18] virtio: pci: Make use of dm_pci_map_bar() Andrew Scull
2022-04-21 16:11 ` [PATCH v3 18/18] pci: Add config for Enhanced Allocation Andrew Scull
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=20220421161116.1202023-11-ascull@google.com \
--to=ascull@google.com \
--cc=bmeng.cn@gmail.com \
--cc=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.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