|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH RFC 13/23] plat/ofw: Support completed ranges mapping
Previously, we only support 1:1 mapping for ranges property. This
is not enough for pci ecam on arm64.
e.g.
pcie@10000000 {
interrupt-map-mask = < 0x1800 0x00 0x00 0x07 >;
interrupt-map = < ... >;
#interrupt-cells = < 0x01 >;
ranges = < 0x1000000 0x00 0x00 0x00 0x3eff0000 0x00 0x10000
0x2000000 0x00 0x10000000 0x00 0x10000000 0x00 0x2eff0000 0x3000000 0x80 0x00
0x80 0x00 0x80 0x00 >;
reg = < 0x40 0x10000000 0x00 0x10000000 >;
msi-parent = < 0x8002 >;
dma-coherent;
bus-range = < 0x00 0xff >;
linux,pci-domain = < 0x00 >;
#size-cells = < 0x02 >;
#address-cells = < 0x03 >;
device_type = "pci";
compatible = "pci-host-ecam-generic";
};
Signed-off-by: Jia He <justin.he@xxxxxxx>
---
plat/drivers/ofw/fdt.c | 46 +++++++++++++++++++++++++++++++++++-------
1 file changed, 39 insertions(+), 7 deletions(-)
diff --git a/plat/drivers/ofw/fdt.c b/plat/drivers/ofw/fdt.c
index c0973311..6c5863c8 100644
--- a/plat/drivers/ofw/fdt.c
+++ b/plat/drivers/ofw/fdt.c
@@ -97,6 +97,24 @@ static void fdt_default_count_cells(const void *fdt, int
parentoffset,
*sizec = fdt_size_cells(fdt, parentoffset);
}
+static __u64 fdt_default_map(fdt32_t *addr, const fdt32_t *range,
+ int na, int ns, int pna)
+{
+ __u64 cp, s, da;
+
+ cp = fdt_reg_read_number(range, na);
+ s = fdt_reg_read_number(range + na + pna, ns);
+ da = fdt_reg_read_number(addr, na);
+
+ uk_pr_debug("default map, cp=%llx, s=%llx, da=%llx\n",
+ (unsigned long long)cp, (unsigned long long)s,
+ (unsigned long long)da);
+
+ if (da < cp || da >= (cp + s))
+ return FDT_BAD_ADDR;
+ return da - cp;
+}
+
static int fdt_default_translate(fdt32_t *addr, uint64_t offset, int na)
{
uint64_t a = fdt_reg_read_number(addr, na);
@@ -111,10 +129,11 @@ static int fdt_default_translate(fdt32_t *addr, uint64_t
offset, int na)
}
static int fdt_translate_one(const void *fdt, int parent, fdt32_t *addr,
- int na, int pna, const char *rprop)
+ int na, int ns, int pna, const char *rprop)
{
const fdt32_t *ranges;
int rlen;
+ int rone;
uint64_t offset = FDT_BAD_ADDR;
ranges = fdt_getprop(fdt, parent, rprop, &rlen);
@@ -126,10 +145,23 @@ static int fdt_translate_one(const void *fdt, int parent,
fdt32_t *addr,
goto finish;
}
- uk_pr_err("Error, only 1:1 translation is supported...\n");
- return 1;
- finish:
- uk_pr_debug("with offset: 0x%lx\n", offset);
+ uk_pr_debug("walking ranges...\n");
+ /* Now walk through the ranges */
+ rlen /= 4;
+ rone = na + pna + ns;
+ for (; rlen >= rone; rlen -= rone, ranges += rone) {
+ offset = fdt_default_map(addr, ranges, na, ns, pna);
+ if (offset != FDT_BAD_ADDR)
+ break;
+ }
+ if (offset == FDT_BAD_ADDR) {
+ uk_pr_debug("not found !\n");
+ return 1;
+ }
+ memcpy(addr, ranges + na, 4 * pna);
+
+finish:
+ uk_pr_info("parent translation for:%llx %llx", addr, pna);
/* Translate it into parent bus space */
return fdt_default_translate(addr, offset, pna);
@@ -140,7 +172,7 @@ static int fdt_translate_one(const void *fdt, int parent,
fdt32_t *addr,
* this walks up the tree and applies the various bus mappings on the
* way.
*/
-static uint64_t fdt_translate_address_by_ranges(const void *fdt,
+uint64_t fdt_translate_address_by_ranges(const void *fdt,
int node_offset, const fdt32_t *regs)
{
int parent;
@@ -188,7 +220,7 @@ static uint64_t fdt_translate_address_by_ranges(const void
*fdt,
/* Apply bus translation */
if (fdt_translate_one(fdt, node_offset,
- addr, na, pna, "ranges"))
+ addr, na, ns, pna, "ranges"))
break;
/* Complete the move up one level */
--
2.17.1
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |