From nobody Wed Nov 30 23:32:00 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NMwTX6Zlqz4jMDP; Wed, 30 Nov 2022 23:32:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NMwTX5shhz4Nhf; Wed, 30 Nov 2022 23:32:00 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1669851120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=xtMSROtPVxnSwHhzCWKqVRlJa4S0CDD0fE7FxiJoJ4E=; b=c2MfIfl3XttMDUHI322HG466v0bzseZRS7pwGm4ulAPJRZoVQZa/Ak9mwArveYaLAr0L0F fddGBRFBKaf2l9+oWyrMV1KFfyezL6FOPPbYF7YUOmVAa2VrYUUGs351gwXLxHjsk0Vday kbXXNxlPKFJxFQzuyjktjJ4nVY1SAPvZTIcU4tM2e9yAq/yzmdMSeKX7YP/C6Qhq4ebJxj r8AYyC/8IoqINTwvKFA2yoMlFX/EkkawOe/gEnIvCaDxYuTteOtGl2YRQtWVY65HQskGw4 hUT8HNYIdSwENByapBLKSNCSDcJns6D2MYSt6Xcq1pPH/KnOOaJENsmwqfSUYA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1669851120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=xtMSROtPVxnSwHhzCWKqVRlJa4S0CDD0fE7FxiJoJ4E=; b=KNBvFlfO1QSaGcgIewTWx6WMWx7Pqg8SVuaNkpJPt9xSAdcwQD8dp/iCpz0E/WHLcteob+ e1s+Wxn+rMBjaqb//w9hYZ9Oo2bu0XZr8JmUpJ29PYdE10osNt0HFtqzQk5TA2yYIJyCAW 9j8F/oqBZadl2bqdvw9PLQLrzmjhhlLd3ap9eADp8QkA1ugppCkjvKlDUJIigPBuqWOse+ fx+v/NFwrbqwRNwBTxGTIIv0SDPDrDu3y7vDZ/Np370U2j9GAS9RJjeX14u82bYHqXUxb8 lPrqiLar+v2IycNkDv5/h9Lyw+6PWndMt909RBMep7r9oM1K5iRihxImLx2A4w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1669851120; a=rsa-sha256; cv=none; b=IlPrVui/MOVp8l1T1db6eeqVUFnw/ZpzevWprWtIUePu5aJ9JJahihwyactZVxHNd0ZRe8 ZuZ/V+eAlgD9N1gQRGI1GSlToHXpUW7alEUwEJHq2Z7YOlFmXLuuqz2yZPIYZ9JAbkA71B jneKhGVlgyOEQwUAPsryoCrufQKgDWM4aVzpVsQhT9UmkrWCQkcDXpX3Amx1I+1S+Gy2T+ S1buDhyAFHwQO7e7kYX4YEJKuJ5Oxne3y1jbEuylJLBCWyr+BnJ1sdyDVNlFMUexuxN6aj 5ptQ7OmcK5NgTGmkXJtWPDLSVnhq3CCGG5Tir2CzPZL9yHvnZGOVO2tEHv6GOA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NMwTX4sbczFnS; Wed, 30 Nov 2022 23:32:00 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2AUNW0F8012707; Wed, 30 Nov 2022 23:32:00 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2AUNW0pO012706; Wed, 30 Nov 2022 23:32:00 GMT (envelope-from git) Date: Wed, 30 Nov 2022 23:32:00 GMT Message-Id: <202211302332.2AUNW0pO012706@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: 0dfc8a7c1c6b - main - arm64/machdep: Reserve memory when we find Linux EFI reserved memory table List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0dfc8a7c1c6b8420fa3fcaf8044bd6016ffa7e0e Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=0dfc8a7c1c6b8420fa3fcaf8044bd6016ffa7e0e commit 0dfc8a7c1c6b8420fa3fcaf8044bd6016ffa7e0e Author: Warner Losh AuthorDate: 2022-11-30 23:28:51 +0000 Commit: Warner Losh CommitDate: 2022-11-30 23:31:14 +0000 arm64/machdep: Reserve memory when we find Linux EFI reserved memory table When Linux loads a new kernel via kexec, somtiems it must reserve memory for devices that are still active (and typically can't be reset or shutdown). When present, this table is a linked list of ranges that are still in use that the OS must avoid using. Mark these areas as reserved. This is part of the GICv3 workaround code where we must use the PA addresses already programmed into the GICv3 when we take over. This part ensure we don't allocate the mmeory for anything else. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D37440 --- sys/arm64/arm64/machdep.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 33635f732cac..b099980634f6 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -580,6 +580,115 @@ print_efi_map_entries(struct efi_map_header *efihdr) foreach_efi_map_entry(efihdr, print_efi_map_entry, NULL); } +/* + * Map the passed in VA in EFI space to a void * using the efi memory table to + * find the PA and return it in the DMAP, if it exists. We're used between the + * calls to pmap_bootstrap() and physmem_init_kernel_globals() to parse CFG + * tables We assume that either the entry you are mapping fits within its page, + * or if it spills to the next page, that's contiguous in PA and in the DMAP. + * All observed tables obey the first part of this precondition. + */ +struct early_map_data +{ + vm_offset_t va; + vm_offset_t pa; +}; + +static void +efi_early_map_entry(struct efi_md *p, void *argp) +{ + struct early_map_data *emdp = argp; + vm_offset_t s, e; + + if (emdp->pa != 0) + return; + if ((p->md_attr & EFI_MD_ATTR_RT) == 0) + return; + s = p->md_virt; + e = p->md_virt + p->md_pages * EFI_PAGE_SIZE; + if (emdp->va < s || emdp->va >= e) + return; + emdp->pa = p->md_phys + (emdp->va - p->md_virt); +} + +static void * +efi_early_map(vm_offset_t va) +{ + struct early_map_data emd = { .va = va }; + + foreach_efi_map_entry(efihdr, efi_early_map_entry, &emd); + if (emd.pa == 0) + return NULL; + return (void *)PHYS_TO_DMAP(emd.pa); +} + + +/* + * When booted via kboot, the prior kernel will pass in reserved memory areas in + * a EFI config table. We need to find that table and walk through it excluding + * the memory ranges in it. btw, this is called too early for the printf to do + * anything since msgbufp isn't initialized, let alone a console... + */ +static void +exclude_efi_memreserve(vm_offset_t efi_systbl_phys) +{ + struct efi_systbl *systbl; + struct uuid efi_memreserve = LINUX_EFI_MEMRESERVE_TABLE; + + systbl = (struct efi_systbl *)PHYS_TO_DMAP(efi_systbl_phys); + if (systbl == NULL) { + printf("can't map systbl\n"); + return; + } + if (systbl->st_hdr.th_sig != EFI_SYSTBL_SIG) { + printf("Bad signature for systbl %#lx\n", systbl->st_hdr.th_sig); + return; + } + + /* + * We don't yet have the pmap system booted enough to create a pmap for + * the efi firmware's preferred address space from the GetMemoryMap() + * table. The st_cfgtbl is a VA in this space, so we need to do the + * mapping ourselves to a kernel VA with efi_early_map. We assume that + * the cfgtbl entries don't span a page. Other pointers are PAs, as + * noted below. + */ + if (systbl->st_cfgtbl == 0) /* Failsafe st_entries should == 0 in this case */ + return; + for (int i = 0; i < systbl->st_entries; i++) { + struct efi_cfgtbl *cfgtbl; + struct linux_efi_memreserve *mr; + + cfgtbl = efi_early_map(systbl->st_cfgtbl + i * sizeof(*cfgtbl)); + if (cfgtbl == NULL) + panic("Can't map the config table entry %d\n", i); + if (memcmp(&cfgtbl->ct_uuid, &efi_memreserve, sizeof(struct uuid)) != 0) + continue; + + /* + * cfgtbl points are either VA or PA, depending on the GUID of + * the table. memreserve GUID pointers are PA and not converted + * after a SetVirtualAddressMap(). The list's mr_next pointer + * is also a PA. + */ + mr = (struct linux_efi_memreserve *)PHYS_TO_DMAP( + (vm_offset_t)cfgtbl->ct_data); + while (true) { + for (int j = 0; j < mr->mr_count; j++) { + struct linux_efi_memreserve_entry *mre; + + mre = &mr->mr_entry[j]; + physmem_exclude_region(mre->mre_base, mre->mre_size, + EXFLAG_NODUMP | EXFLAG_NOALLOC); + } + if (mr->mr_next == 0) + break; + mr = (struct linux_efi_memreserve *)PHYS_TO_DMAP(mr->mr_next); + }; + } + +} + #ifdef FDT static void try_load_dtb(caddr_t kmdp) @@ -825,6 +934,9 @@ initarm(struct arm64_bootparams *abp) /* Exclude entries needed in the DMAP region, but not phys_avail */ if (efihdr != NULL) exclude_efi_map_entries(efihdr); + /* Do the same for reserve entries in the EFI MEMRESERVE table */ + if (efi_systbl_phys != 0) + exclude_efi_memreserve(efi_systbl_phys); physmem_init_kernel_globals(); devmap_bootstrap(0, NULL);