svn commit: r251962 - in stable/9/sys: conf ia64/ia64 ia64/include
Marius Strobl
marius at FreeBSD.org
Tue Jun 18 21:14:07 UTC 2013
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_ */
More information about the svn-src-stable-9
mailing list