Index: sys/arm64/acpica/acpi_machdep.c =================================================================== --- sys/arm64/acpica/acpi_machdep.c +++ sys/arm64/acpica/acpi_machdep.c @@ -232,47 +232,12 @@ static void parse_pxm_tables(void *dummy) { - uint64_t mmfr0, parange; /* Only parse ACPI tables when booting via ACPI */ if (arm64_bus_method != ARM64_BUS_ACPI) return; - 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; - } - - acpi_pxm_init(MAXCPU, parange); + acpi_pxm_init(MAXCPU, get_physaddr_max()); acpi_pxm_parse_tables(); acpi_pxm_set_mem_locality(); } Index: sys/arm64/arm64/machdep.c =================================================================== --- sys/arm64/arm64/machdep.c +++ sys/arm64/arm64/machdep.c @@ -910,6 +910,54 @@ mtx_lock(&psp->ps_mtx); } +/* return the number of physical address bits */ +static inline u_int +get_physaddr_bits(void) +{ + uint64_t mmfr0, parange; + + const int mapping[] = { + [ID_AA64MMFR0_PARange_4G] = 32, + [ID_AA64MMFR0_PARange_64G] = 36, + [ID_AA64MMFR0_PARange_1T] = 40, + [ID_AA64MMFR0_PARange_4T] = 42, + [ID_AA64MMFR0_PARange_16T] = 44, + [ID_AA64MMFR0_PARange_256T] = 48, + [ID_AA64MMFR0_PARange_4P] = 52, + /* ensure the last entry is defined */ + [ID_AA64MMFR0_PARange_MASK] = 0 + }; + + if (!get_kernel_reg(ID_AA64MMFR0_EL1, &mmfr0)) { + printf("WARNING: Unable to retrieve MMRF0 register!\n"); + /* a conservative default */ + return (40); + } + parange = ID_AA64MMFR0_PARange_VAL(mmfr0) >> ID_AA64MMFR0_PARange_SHIFT; + if (mapping[parange] == 0) { + printf("WARNING: Unknown value for PARange in MMFR0 (%#lx)\n", mmfr0); + /* a conservative default */ + return (40); + } + return (mapping[parange]); +} + +/* return the number of physical addresses */ +static inline uint64_t +get_physaddr_count(void) +{ + + return (1ul << get_physaddr_bits()); +} + +/* return the maximum valid physical address */ +uint64_t +get_physaddr_max(void) +{ + + return (get_physaddr_count() - 1); +} + static void init_proc0(vm_offset_t kstack) { Index: sys/arm64/arm64/nexus.c =================================================================== --- sys/arm64/arm64/nexus.c +++ sys/arm64/arm64/nexus.c @@ -163,11 +163,11 @@ { mem_rman.rm_start = 0; - mem_rman.rm_end = BUS_SPACE_MAXADDR; + mem_rman.rm_end = get_physaddr_max(); 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; Index: sys/arm64/include/cpu.h =================================================================== --- sys/arm64/include/cpu.h +++ sys/arm64/include/cpu.h @@ -207,6 +207,9 @@ ADDRESS_TRANSLATE_FUNC(s1e1r) ADDRESS_TRANSLATE_FUNC(s1e1w) +/* retrieve the maximum valid physical address */ +extern uint64_t get_physaddr_max(void); + #endif #endif /* !_MACHINE_CPU_H_ */