Date: Tue, 18 Jun 2013 21:14:06 +0000 (UTC) From: Marius Strobl <marius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r251962 - in stable/9/sys: conf ia64/ia64 ia64/include Message-ID: <201306182114.r5ILE6lF016088@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marius Date: Tue Jun 18 21:14:05 2013 New Revision: 251962 URL: http://svnweb.freebsd.org/changeset/base/251962 Log: MFC: r238184 Hide the creation of phys_avail behind an API to make it easier to do it correctly. We now iterate the EFI memory descriptors once and collect all the information in a single pass. Added: stable/9/sys/ia64/ia64/physmem.c - copied unchanged from r238184, head/sys/ia64/ia64/physmem.c Modified: stable/9/sys/conf/files.ia64 stable/9/sys/ia64/ia64/busdma_machdep.c stable/9/sys/ia64/ia64/machdep.c stable/9/sys/ia64/include/md_var.h stable/9/sys/ia64/include/param.h Directory Properties: stable/9/sys/ (props changed) stable/9/sys/conf/ (props changed) Modified: stable/9/sys/conf/files.ia64 ============================================================================== --- stable/9/sys/conf/files.ia64 Tue Jun 18 20:19:09 2013 (r251961) +++ stable/9/sys/conf/files.ia64 Tue Jun 18 21:14:05 2013 (r251962) @@ -97,6 +97,7 @@ ia64/ia64/mp_machdep.c optional smp ia64/ia64/nexus.c standard ia64/ia64/pal.S standard ia64/ia64/physical.S standard +ia64/ia64/physmem.c standard ia64/ia64/pmap.c standard ia64/ia64/ptrace_machdep.c standard ia64/ia64/sal.c standard Modified: stable/9/sys/ia64/ia64/busdma_machdep.c ============================================================================== --- stable/9/sys/ia64/ia64/busdma_machdep.c Tue Jun 18 20:19:09 2013 (r251961) +++ stable/9/sys/ia64/ia64/busdma_machdep.c Tue Jun 18 21:14:05 2013 (r251962) @@ -262,7 +262,7 @@ bus_dma_tag_create(bus_dma_tag_t parent, atomic_add_int(&parent->ref_count, 1); } - if (newtag->lowaddr < ptoa(Maxmem) && (flags & BUS_DMA_ALLOCNOW) != 0) { + if (newtag->lowaddr < paddr_max && (flags & BUS_DMA_ALLOCNOW) != 0) { /* Must bounce */ if (ptoa(total_bpages) < maxsize) { @@ -340,7 +340,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, in * exclusion region, a data alignment that is stricter than 1, and/or * an active address boundary. */ - if (dmat->lowaddr < ptoa(Maxmem)) { + if (dmat->lowaddr < paddr_max) { /* Must bounce */ int maxpages; @@ -356,7 +356,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, in * Attempt to add pages to our pool on a per-instance * basis up to a sane limit. */ - maxpages = MIN(MAX_BPAGES, Maxmem - atop(dmat->lowaddr)); + maxpages = MIN(MAX_BPAGES, atop(paddr_max - dmat->lowaddr)); if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0 || (dmat->map_count > 0 && total_bpages < maxpages)) { int pages; @@ -438,7 +438,7 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi */ if ((dmat->maxsize <= PAGE_SIZE) && (dmat->alignment < dmat->maxsize) && - dmat->lowaddr >= ptoa(Maxmem)) { + dmat->lowaddr >= paddr_max) { *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); } else { /* @@ -473,7 +473,7 @@ bus_dmamem_free(bus_dma_tag_t dmat, void panic("bus_dmamem_free: Invalid map freed\n"); if ((dmat->maxsize <= PAGE_SIZE) && (dmat->alignment < dmat->maxsize) && - dmat->lowaddr >= ptoa(Maxmem)) + dmat->lowaddr >= paddr_max) free(vaddr, M_DEVBUF); else { contigfree(vaddr, dmat->maxsize, M_DEVBUF); @@ -515,7 +515,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dm vm_offset_t vendaddr; bus_addr_t paddr; - if ((dmat->lowaddr < ptoa(Maxmem) || dmat->boundary > 0 || + if ((dmat->lowaddr < paddr_max || dmat->boundary > 0 || dmat->alignment > 1) && map != &nobounce_dmamap && map->pagesneeded == 0) { /* Modified: stable/9/sys/ia64/ia64/machdep.c ============================================================================== --- stable/9/sys/ia64/ia64/machdep.c Tue Jun 18 20:19:09 2013 (r251961) +++ stable/9/sys/ia64/ia64/machdep.c Tue Jun 18 21:14:05 2013 (r251962) @@ -168,22 +168,11 @@ SYSCTL_STRING(_hw, OID_AUTO, family, CTL extern vm_offset_t ksym_start, ksym_end; #endif - struct msgbuf *msgbufp = NULL; /* Other subsystems (e.g., ACPI) can hook this later. */ void (*cpu_idle_hook)(void) = NULL; -long Maxmem = 0; -long realmem = 0; - -#define PHYSMAP_SIZE (2 * VM_PHYSSEG_MAX) - -vm_paddr_t phys_avail[PHYSMAP_SIZE + 2]; - -/* must be 2 less so 0 0 can signal end of chunks */ -#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) - struct kva_md_info kmi; #define Mhz 1000000L @@ -286,25 +275,8 @@ cpu_startup(void *dummy) #ifdef PERFMON perfmon_init(); #endif - printf("real memory = %ld (%ld MB)\n", ia64_ptob(Maxmem), - ia64_ptob(Maxmem) / 1048576); - realmem = Maxmem; - - /* - * Display any holes after the first chunk of extended memory. - */ - if (bootverbose) { - int indx; - - printf("Physical memory chunk(s):\n"); - for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { - long size1 = phys_avail[indx + 1] - phys_avail[indx]; - - printf("0x%08lx - 0x%08lx, %ld bytes (%ld pages)\n", - phys_avail[indx], phys_avail[indx + 1] - 1, size1, - size1 >> PAGE_SHIFT); - } - } + printf("real memory = %ld (%ld MB)\n", ptoa(realmem), + ptoa(realmem) / 1048576); vm_ksubmap_init(&kmi); @@ -716,43 +688,87 @@ struct ia64_init_return ia64_init(void) { struct ia64_init_return ret; - int phys_avail_cnt; - vm_offset_t kernstart, kernend; - vm_offset_t kernstartpfn, kernendpfn, pfn0, pfn1; - char *p; struct efi_md *md; + pt_entry_t *pbvm_pgtbl_ent, *pbvm_pgtbl_lim; + char *p; + vm_offset_t kernend; + vm_size_t mdlen; int metadata_missing; - /* NO OUTPUT ALLOWED UNTIL FURTHER NOTICE */ - /* - * TODO: Disable interrupts, floating point etc. - * Maybe flush cache and tlb + * NO OUTPUT ALLOWED UNTIL FURTHER NOTICE. */ + ia64_set_fpsr(IA64_FPSR_DEFAULT); /* - * TODO: Get critical system information (if possible, from the - * information provided by the boot program). + * Region 6 is direct mapped UC and region 7 is direct mapped + * WC. The details of this is controlled by the Alt {I,D}TLB + * handlers. Here we just make sure that they have the largest + * possible page size to minimise TLB usage. */ + ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (PAGE_SHIFT << 2)); + ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (PAGE_SHIFT << 2)); + ia64_srlz_d(); + + /* Initialize/setup physical memory datastructures */ + ia64_physmem_init(); /* - * Look for the I/O ports first - we need them for console - * probing. + * Process the memory map. This gives us the PAL locations, + * the I/O port base address, the available memory regions + * for initializing the physical memory map. */ for (md = efi_md_first(); md != NULL; md = efi_md_next(md)) { + mdlen = md->md_pages * EFI_PAGE_SIZE; switch (md->md_type) { case EFI_MD_TYPE_IOPORT: ia64_port_base = (uintptr_t)pmap_mapdev(md->md_phys, - md->md_pages * EFI_PAGE_SIZE); + mdlen); break; case EFI_MD_TYPE_PALCODE: - ia64_pal_size = md->md_pages * EFI_PAGE_SIZE; ia64_pal_base = md->md_phys; + ia64_pal_size = mdlen; + /*FALLTHROUGH*/ + case EFI_MD_TYPE_BAD: + case EFI_MD_TYPE_FIRMWARE: + case EFI_MD_TYPE_RECLAIM: + case EFI_MD_TYPE_RT_CODE: + case EFI_MD_TYPE_RT_DATA: + /* Don't use these memory regions. */ + ia64_physmem_track(md->md_phys, mdlen); + break; + case EFI_MD_TYPE_BS_CODE: + case EFI_MD_TYPE_BS_DATA: + case EFI_MD_TYPE_CODE: + case EFI_MD_TYPE_DATA: + case EFI_MD_TYPE_FREE: + /* These are ok to use. */ + ia64_physmem_add(md->md_phys, mdlen); break; } } + /* + * Remove the PBVM and its page table from phys_avail. The loader + * passes the physical address of the page table to us. The virtual + * address of the page table is fixed. + * Track and the PBVM limit for later use. + */ + ia64_physmem_delete(bootinfo->bi_pbvm_pgtbl, bootinfo->bi_pbvm_pgtblsz); + pbvm_pgtbl_ent = (void *)IA64_PBVM_PGTBL; + pbvm_pgtbl_lim = (void *)(IA64_PBVM_PGTBL + bootinfo->bi_pbvm_pgtblsz); + while (pbvm_pgtbl_ent < pbvm_pgtbl_lim) { + if ((*pbvm_pgtbl_ent & PTE_PRESENT) == 0) + break; + ia64_physmem_delete(*pbvm_pgtbl_ent & PTE_PPN_MASK, + IA64_PBVM_PAGE_SIZE); + pbvm_pgtbl_ent++; + } + + /* Finalize physical memory datastructures */ + ia64_physmem_fini(); + metadata_missing = 0; if (bootinfo->bi_modulep) preload_metadata = (caddr_t)bootinfo->bi_modulep; @@ -773,9 +789,8 @@ ia64_init(void) bootverbose = 1; /* - * Find the beginning and end of the kernel. + * Find the end of the kernel. */ - kernstart = trunc_page(kernel_text); #ifdef DDB ksym_start = bootinfo->bi_symtab; ksym_end = bootinfo->bi_esymtab; @@ -788,16 +803,6 @@ ia64_init(void) kernend = round_page(bootinfo->bi_kernend); /* - * Region 6 is direct mapped UC and region 7 is direct mapped - * WC. The details of this is controlled by the Alt {I,D}TLB - * handlers. Here we just make sure that they have the largest - * possible page size to minimise TLB usage. - */ - ia64_set_rr(IA64_RR_BASE(6), (6 << 8) | (PAGE_SHIFT << 2)); - ia64_set_rr(IA64_RR_BASE(7), (7 << 8) | (PAGE_SHIFT << 2)); - ia64_srlz_d(); - - /* * Wire things up so we can call the firmware. */ map_pal_code(); @@ -844,92 +849,6 @@ ia64_init(void) freeenv(p); } - kernstartpfn = atop(IA64_RR_MASK(kernstart)); - kernendpfn = atop(IA64_RR_MASK(kernend)); - - /* - * Size the memory regions and load phys_avail[] with the results. - */ - - /* - * Find out how much memory is available, by looking at - * the memory descriptors. - */ - -#ifdef DEBUG_MD - printf("Memory descriptor count: %d\n", mdcount); -#endif - - phys_avail_cnt = 0; - for (md = efi_md_first(); md != NULL; md = efi_md_next(md)) { -#ifdef DEBUG_MD - printf("MD %p: type %d pa 0x%lx cnt 0x%lx\n", md, - md->md_type, md->md_phys, md->md_pages); -#endif - - pfn0 = ia64_btop(round_page(md->md_phys)); - pfn1 = ia64_btop(trunc_page(md->md_phys + md->md_pages * 4096)); - if (pfn1 <= pfn0) - continue; - - if (md->md_type != EFI_MD_TYPE_FREE) - continue; - - /* - * We have a memory descriptor that describes conventional - * memory that is for general use. We must determine if the - * loader has put the kernel in this region. - */ - physmem += (pfn1 - pfn0); - if (pfn0 <= kernendpfn && kernstartpfn <= pfn1) { - /* - * Must compute the location of the kernel - * within the segment. - */ -#ifdef DEBUG_MD - printf("Descriptor %p contains kernel\n", mp); -#endif - if (pfn0 < kernstartpfn) { - /* - * There is a chunk before the kernel. - */ -#ifdef DEBUG_MD - printf("Loading chunk before kernel: " - "0x%lx / 0x%lx\n", pfn0, kernstartpfn); -#endif - phys_avail[phys_avail_cnt] = ia64_ptob(pfn0); - phys_avail[phys_avail_cnt+1] = ia64_ptob(kernstartpfn); - phys_avail_cnt += 2; - } - if (kernendpfn < pfn1) { - /* - * There is a chunk after the kernel. - */ -#ifdef DEBUG_MD - printf("Loading chunk after kernel: " - "0x%lx / 0x%lx\n", kernendpfn, pfn1); -#endif - phys_avail[phys_avail_cnt] = ia64_ptob(kernendpfn); - phys_avail[phys_avail_cnt+1] = ia64_ptob(pfn1); - phys_avail_cnt += 2; - } - } else { - /* - * Just load this cluster as one chunk. - */ -#ifdef DEBUG_MD - printf("Loading descriptor %d: 0x%lx / 0x%lx\n", i, - pfn0, pfn1); -#endif - phys_avail[phys_avail_cnt] = ia64_ptob(pfn0); - phys_avail[phys_avail_cnt+1] = ia64_ptob(pfn1); - phys_avail_cnt += 2; - - } - } - phys_avail[phys_avail_cnt] = 0; - - Maxmem = physmem; init_param2(physmem); /* Copied: stable/9/sys/ia64/ia64/physmem.c (from r238184, head/sys/ia64/ia64/physmem.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/9/sys/ia64/ia64/physmem.c Tue Jun 18 21:14:05 2013 (r251962, copy of r238184, head/sys/ia64/ia64/physmem.c) @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2012 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> + +#include <machine/md_var.h> +#include <machine/vmparam.h> + +static u_int phys_avail_segs; + +vm_paddr_t phys_avail[2 * VM_PHYSSEG_MAX + 2]; + +vm_paddr_t paddr_max; + +long realmem; + +static u_int +ia64_physmem_find(vm_paddr_t base, vm_paddr_t lim) +{ + u_int idx; + + for (idx = 0; phys_avail[idx + 1] != 0; idx += 2) { + if (phys_avail[idx] >= lim || + phys_avail[idx + 1] > base) + break; + } + return (idx); +} + +static int +ia64_physmem_insert(u_int idx, vm_paddr_t base, vm_paddr_t lim) +{ + u_int ridx; + + if (phys_avail_segs == VM_PHYSSEG_MAX) + return (ENOMEM); + + ridx = phys_avail_segs * 2; + while (idx < ridx) { + phys_avail[ridx + 1] = phys_avail[ridx - 1]; + phys_avail[ridx] = phys_avail[ridx - 2]; + ridx -= 2; + } + phys_avail[idx] = base; + phys_avail[idx + 1] = lim; + phys_avail_segs++; + return (0); +} + +static int +ia64_physmem_remove(u_int idx) +{ + + if (phys_avail_segs == 0) + return (ENOENT); + do { + phys_avail[idx] = phys_avail[idx + 2]; + phys_avail[idx + 1] = phys_avail[idx + 3]; + idx += 2; + } while (phys_avail[idx + 1] != 0); + phys_avail_segs--; + return (0); +} + +int +ia64_physmem_add(vm_paddr_t base, vm_size_t len) +{ + vm_paddr_t lim; + u_int idx; + + realmem += len; + + lim = base + len; + idx = ia64_physmem_find(base, lim); + if (phys_avail[idx] == lim) { + phys_avail[idx] = base; + return (0); + } + if (idx > 0 && phys_avail[idx - 1] == base) { + phys_avail[idx - 1] = lim; + return (0); + } + return (ia64_physmem_insert(idx, base, lim)); +} + +int +ia64_physmem_delete(vm_paddr_t base, vm_size_t len) +{ + vm_paddr_t lim; + u_int idx; + + lim = base + len; + idx = ia64_physmem_find(base, lim); + if (phys_avail[idx] >= lim || phys_avail[idx + 1] == 0) + return (ENOENT); + if (phys_avail[idx] < base && phys_avail[idx + 1] > lim) { + len = phys_avail[idx + 1] - lim; + phys_avail[idx + 1] = base; + base = lim; + lim = base + len; + return (ia64_physmem_insert(idx + 2, base, lim)); + } else { + if (phys_avail[idx] == base) + phys_avail[idx] = lim; + if (phys_avail[idx + 1] == lim) + phys_avail[idx + 1] = base; + if (phys_avail[idx] >= phys_avail[idx + 1]) + return (ia64_physmem_remove(idx)); + } + return (0); +} + +int +ia64_physmem_fini(void) +{ + vm_paddr_t base, lim, size; + u_int idx; + + idx = 0; + while (phys_avail[idx + 1] != 0) { + base = round_page(phys_avail[idx]); + lim = trunc_page(phys_avail[idx + 1]); + if (base < lim) { + phys_avail[idx] = base; + phys_avail[idx + 1] = lim; + size = lim - base; + physmem += atop(size); + paddr_max = lim; + idx += 2; + } else + ia64_physmem_remove(idx); + } + + /* + * Round realmem to a multple of 128MB. Hopefully that compensates + * for any loss of DRAM that isn't accounted for in the memory map. + * I'm thinking legacy BIOS or VGA here. In any case, it's ok if + * we got it wrong, because we don't actually use realmem. It's + * just for show... + */ + size = 1U << 27; + realmem = (realmem + size - 1) & ~(size - 1); + realmem = atop(realmem); + return (0); +} + +int +ia64_physmem_init(void) +{ + + /* Nothing to do just yet. */ + return (0); +} + +int +ia64_physmem_track(vm_paddr_t base, vm_size_t len) +{ + + realmem += len; + return (0); +} + +vm_paddr_t +ia64_physmem_alloc(vm_size_t len, vm_size_t align) +{ + + return (0); +} Modified: stable/9/sys/ia64/include/md_var.h ============================================================================== --- stable/9/sys/ia64/include/md_var.h Tue Jun 18 20:19:09 2013 (r251961) +++ stable/9/sys/ia64/include/md_var.h Tue Jun 18 21:14:05 2013 (r251962) @@ -73,8 +73,7 @@ struct ia64_init_return { }; extern uint64_t ia64_lapic_addr; - -extern long Maxmem; +extern vm_paddr_t paddr_max; extern u_int busdma_swi_pending; void *acpi_find_table(const char *sig); @@ -93,6 +92,12 @@ int ia64_highfp_save(struct thread *); int ia64_highfp_save_ipi(void); struct ia64_init_return ia64_init(void); u_int ia64_itc_freq(void); +int ia64_physmem_add(vm_paddr_t, vm_size_t); +vm_paddr_t ia64_physmem_alloc(vm_size_t, vm_size_t); +int ia64_physmem_delete(vm_paddr_t, vm_size_t); +int ia64_physmem_fini(void); +int ia64_physmem_init(void); +int ia64_physmem_track(vm_paddr_t, vm_size_t); void ia64_probe_sapics(void); void ia64_sync_icache(vm_offset_t, vm_size_t); void interrupt(struct trapframe *); Modified: stable/9/sys/ia64/include/param.h ============================================================================== --- stable/9/sys/ia64/include/param.h Tue Jun 18 20:19:09 2013 (r251961) +++ stable/9/sys/ia64/include/param.h Tue Jun 18 21:14:05 2013 (r251962) @@ -110,9 +110,6 @@ #define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) #define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) -#define ia64_btop(x) ((unsigned long)(x) >> PAGE_SHIFT) -#define ia64_ptob(x) ((unsigned long)(x) << PAGE_SHIFT) - #define pgtok(x) ((x) * (PAGE_SIZE / 1024)) #endif /* !_IA64_INCLUDE_PARAM_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306182114.r5ILE6lF016088>