Index: sys/arm64/arm64/nexus.c =================================================================== --- sys/arm64/arm64/nexus.c +++ sys/arm64/arm64/nexus.c @@ -118,6 +118,8 @@ static int nexus_release_resource(device_t, device_t, int, int, struct resource *); +static uint64_t nexus_get_parange(void); + static int nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep); static int nexus_teardown_intr(device_t, device_t, struct resource *, void *); @@ -163,11 +165,11 @@ { mem_rman.rm_start = 0; - mem_rman.rm_end = BUS_SPACE_MAXADDR; + mem_rman.rm_end = nexus_get_parange(); mem_rman.rm_type = RMAN_ARRAY; mem_rman.rm_descr = "I/O memory addresses"; if (rman_init(&mem_rman) || - rman_manage_region(&mem_rman, 0, BUS_SPACE_MAXADDR)) + rman_manage_region(&mem_rman, 0, mem_rman.rm_end)) panic("nexus_attach mem_rman"); irq_rman.rm_start = 0; irq_rman.rm_end = ~0; @@ -480,6 +482,48 @@ return (0); } +static uint64_t +nexus_get_parange(void) +{ + uint64_t mmfr0, parange; + + if (!get_kernel_reg(ID_AA64MMFR0_EL1, &mmfr0)) { + /* chosen arbitrarily */ + mmfr0 = ID_AA64MMFR0_PARange_1T; + } + + switch (ID_AA64MMFR0_PARange_VAL(mmfr0)) { + case ID_AA64MMFR0_PARange_4G: + parange = (vm_paddr_t)4 << 30 /* GiB */; + break; + case ID_AA64MMFR0_PARange_64G: + parange = (vm_paddr_t)64 << 30 /* GiB */; + break; + case ID_AA64MMFR0_PARange_1T: + parange = (vm_paddr_t)1 << 40 /* TiB */; + break; + case ID_AA64MMFR0_PARange_4T: + parange = (vm_paddr_t)4 << 40 /* TiB */; + break; + case ID_AA64MMFR0_PARange_16T: + parange = (vm_paddr_t)16 << 40 /* TiB */; + break; + case ID_AA64MMFR0_PARange_256T: + parange = (vm_paddr_t)256 << 40 /* TiB */; + break; + case ID_AA64MMFR0_PARange_4P: + parange = (vm_paddr_t)4 << 50 /* PiB */; + break; + default: + /* chosen arbitrarily */ + parange = (vm_paddr_t)1 << 40 /* TiB */; + printf("Unknown value for PARange in mmfr0 (%#lx)\n", mmfr0); + break; + } + + return (parange); +} + #ifdef FDT static device_method_t nexus_fdt_methods[] = { /* Device interface */