Make bus_space map machine addresses instead of physical addresses.
This commit is contained in:
parent
4c5f9e53a1
commit
fb658556ac
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files.xen,v 1.6 2004/04/24 18:24:14 cl Exp $
|
||||
# $NetBSD: files.xen,v 1.7 2004/04/24 19:18:01 cl Exp $
|
||||
# NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp
|
||||
# NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp
|
||||
|
||||
|
@ -85,7 +85,7 @@ file dev/md_root.c memory_disk_hooks
|
|||
define mainbus { [apid = -1] }
|
||||
|
||||
file arch/x86/x86/bus_dma.c
|
||||
file arch/x86/x86/bus_space.c
|
||||
file arch/xen/x86/bus_space.c
|
||||
file arch/x86/x86/cacheinfo.c
|
||||
file arch/xen/x86/consinit.c
|
||||
file arch/xen/x86/intr.c
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pmap.c,v 1.3 2004/04/17 12:53:27 cl Exp $ */
|
||||
/* $NetBSD: pmap.c,v 1.4 2004/04/24 19:18:01 cl Exp $ */
|
||||
/* NetBSD: pmap.c,v 1.172 2004/04/12 13:17:46 yamt Exp */
|
||||
|
||||
/*
|
||||
|
@ -61,7 +61,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.3 2004/04/17 12:53:27 cl Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.4 2004/04/24 19:18:01 cl Exp $");
|
||||
|
||||
#include "opt_cputype.h"
|
||||
#include "opt_user_ldt.h"
|
||||
|
@ -3626,6 +3626,186 @@ out:
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_enter_ma: enter a mapping into a pmap
|
||||
*
|
||||
* => must be done "now" ... no lazy-evaluation
|
||||
* => we set pmap => pv_head locking
|
||||
*/
|
||||
|
||||
int
|
||||
pmap_enter_ma(pmap, va, pa, prot, flags)
|
||||
struct pmap *pmap;
|
||||
vaddr_t va;
|
||||
paddr_t pa;
|
||||
vm_prot_t prot;
|
||||
int flags;
|
||||
{
|
||||
pt_entry_t *ptes, opte, npte;
|
||||
struct vm_page *ptp, *pg;
|
||||
int error;
|
||||
boolean_t wired = (flags & PMAP_WIRED) != 0;
|
||||
|
||||
XENPRINTK(("pmap_enter_ma(%p, %p, %p, %08x, %08x)\n",
|
||||
pmap, (void *)va, (void *)pa, prot, flags));
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/* sanity check: totally out of range? */
|
||||
if (va >= VM_MAX_KERNEL_ADDRESS)
|
||||
panic("pmap_enter: too big");
|
||||
|
||||
if (va == (vaddr_t) PDP_BASE || va == (vaddr_t) APDP_BASE)
|
||||
panic("pmap_enter: trying to map over PDP/APDP!");
|
||||
|
||||
/* sanity check: kernel PTPs should already have been pre-allocated */
|
||||
if (va >= VM_MIN_KERNEL_ADDRESS &&
|
||||
!pmap_valid_entry(pmap->pm_pdir[pdei(va)]))
|
||||
panic("pmap_enter: missing kernel PTP!");
|
||||
#endif
|
||||
|
||||
npte = pa | protection_codes[prot] | PG_V;
|
||||
/* XENPRINTK(("npte %p\n", npte)); */
|
||||
|
||||
if (wired)
|
||||
npte |= PG_W;
|
||||
|
||||
if (va < VM_MAXUSER_ADDRESS)
|
||||
npte |= PG_u;
|
||||
else if (va < VM_MAX_ADDRESS)
|
||||
npte |= (PG_u | PG_RW); /* XXXCDC: no longer needed? */
|
||||
if (pmap == pmap_kernel())
|
||||
npte |= pmap_pg_g;
|
||||
|
||||
/* get lock */
|
||||
PMAP_MAP_TO_HEAD_LOCK();
|
||||
|
||||
ptes = pmap_map_ptes(pmap); /* locks pmap */
|
||||
if (pmap == pmap_kernel()) {
|
||||
ptp = NULL;
|
||||
} else {
|
||||
ptp = pmap_get_ptp(pmap, pdei(va));
|
||||
if (ptp == NULL) {
|
||||
if (flags & PMAP_CANFAIL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
panic("pmap_enter: get ptp failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get first view on old PTE
|
||||
* on SMP the PTE might gain PG_U and PG_M flags
|
||||
* before we zap it later
|
||||
*/
|
||||
opte = ptes[x86_btop(va)]; /* old PTE */
|
||||
XENPRINTK(("npte %p opte %p ptes %p idx %03x\n",
|
||||
(void *)npte, (void *)opte, ptes, x86_btop(va)));
|
||||
|
||||
/*
|
||||
* is there currently a valid mapping at our VA and does it
|
||||
* map to the same PA as the one we want to map ?
|
||||
*/
|
||||
|
||||
if (pmap_valid_entry(opte) && ((opte & PG_FRAME) == pa)) {
|
||||
|
||||
/*
|
||||
* first, calculate pm_stats updates. resident count will not
|
||||
* change since we are replacing/changing a valid mapping.
|
||||
* wired count might change...
|
||||
*/
|
||||
pmap->pm_stats.wired_count +=
|
||||
((npte & PG_W) ? 1 : 0 - (opte & PG_W) ? 1 : 0);
|
||||
|
||||
XENPRINTK(("pmap update opte == pa"));
|
||||
/* zap! */
|
||||
PTE_ATOMIC_SET_MA(&ptes[x86_btop(va)], npte, opte);
|
||||
|
||||
/*
|
||||
* Any change in the protection level that the CPU
|
||||
* should know about ?
|
||||
*/
|
||||
if ((npte & PG_RW)
|
||||
|| ((opte & (PG_M | PG_RW)) != (PG_M | PG_RW))) {
|
||||
XENPRINTK(("pmap update opte == pa, prot change"));
|
||||
/*
|
||||
* No need to flush the TLB.
|
||||
* Just add old PG_M, ... flags in new entry.
|
||||
*/
|
||||
PTE_ATOMIC_SETBITS(&ptes[x86_btop(va)],
|
||||
opte & (PG_M | PG_U));
|
||||
goto out_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Might be cached in the TLB as being writable
|
||||
* if this is on the PVLIST, sync R/M bit
|
||||
*/
|
||||
KDASSERT((opte & PG_PVLIST) == 0);
|
||||
goto shootdown_now;
|
||||
}
|
||||
|
||||
pg = PHYS_TO_VM_PAGE(pa);
|
||||
XENPRINTK(("pg %p from %p, init %d\n", pg, (void *)pa,
|
||||
pmap_initialized));
|
||||
|
||||
/*
|
||||
* is there currently a valid mapping at our VA?
|
||||
*/
|
||||
|
||||
if (pmap_valid_entry(opte)) {
|
||||
|
||||
/*
|
||||
* changing PAs: we must remove the old one first
|
||||
*/
|
||||
|
||||
/*
|
||||
* first, calculate pm_stats updates. resident count will not
|
||||
* change since we are replacing/changing a valid mapping.
|
||||
* wired count might change...
|
||||
*/
|
||||
pmap->pm_stats.wired_count +=
|
||||
((npte & PG_W) ? 1 : 0 - (opte & PG_W) ? 1 : 0);
|
||||
|
||||
KDASSERT((opte & PG_PVLIST) == 0);
|
||||
} else { /* opte not valid */
|
||||
pmap->pm_stats.resident_count++;
|
||||
if (wired)
|
||||
pmap->pm_stats.wired_count++;
|
||||
if (ptp)
|
||||
ptp->wire_count++;
|
||||
}
|
||||
|
||||
XENPRINTK(("pmap initial setup"));
|
||||
PTE_ATOMIC_SET_MA(&ptes[x86_btop(va)], npte, opte); /* zap! */
|
||||
|
||||
/* Update page attributes if needed */
|
||||
if ((opte & (PG_V | PG_U)) == (PG_V | PG_U)) {
|
||||
#if defined(MULTIPROCESSOR)
|
||||
int32_t cpumask = 0;
|
||||
#endif
|
||||
shootdown_now:
|
||||
#if defined(MULTIPROCESSOR)
|
||||
pmap_tlb_shootdown(pmap, va, opte, &cpumask);
|
||||
pmap_tlb_shootnow(cpumask);
|
||||
#else
|
||||
/* Don't bother deferring in the single CPU case. */
|
||||
if (pmap_is_curpmap(pmap))
|
||||
pmap_update_pg(va);
|
||||
#endif
|
||||
}
|
||||
|
||||
out_ok:
|
||||
error = 0;
|
||||
|
||||
out:
|
||||
pmap_unmap_ptes(pmap);
|
||||
PMAP_MAP_TO_HEAD_UNLOCK();
|
||||
|
||||
XENPRINTK(("pmap_enter: %d\n", error));
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_growkernel: increase usage of KVM space
|
||||
*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pmap.h,v 1.2 2004/04/10 23:47:24 cl Exp $ */
|
||||
/* $NetBSD: pmap.h,v 1.3 2004/04/24 19:18:01 cl Exp $ */
|
||||
/* NetBSD: pmap.h,v 1.79 2004/02/20 17:35:01 yamt Exp */
|
||||
|
||||
/*
|
||||
|
@ -352,6 +352,8 @@ void pmap_write_protect(struct pmap *, vaddr_t, vaddr_t, vm_prot_t);
|
|||
int pmap_exec_fixup(struct vm_map *, struct trapframe *,
|
||||
struct pcb *);
|
||||
void pmap_load(void);
|
||||
int pmap_enter_ma(struct pmap *, vaddr_t, paddr_t, vm_prot_t,
|
||||
int);
|
||||
|
||||
vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */
|
||||
|
||||
|
|
|
@ -0,0 +1,503 @@
|
|||
/* $NetBSD: bus_space.c,v 1.1 2004/04/24 19:18:01 cl Exp $ */
|
||||
/* NetBSD: bus_space.c,v 1.2 2003/03/14 18:47:53 christos Exp */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
|
||||
* Simulation Facility, NASA Ames Research Center.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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>
|
||||
__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.1 2004/04/24 19:18:01 cl Exp $");
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/extent.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <machine/isa_machdep.h>
|
||||
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/xenpmap.h>
|
||||
|
||||
/*
|
||||
* Extent maps to manage I/O and memory space. Allocate
|
||||
* storage for 8 regions in each, initially. Later, ioport_malloc_safe
|
||||
* will indicate that it's safe to use malloc() to dynamically allocate
|
||||
* region descriptors.
|
||||
*
|
||||
* N.B. At least two regions are _always_ allocated from the iomem
|
||||
* extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM).
|
||||
*
|
||||
* The extent maps are not static! Machine-dependent ISA and EISA
|
||||
* routines need access to them for bus address space allocation.
|
||||
*/
|
||||
static long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
|
||||
static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
|
||||
struct extent *ioport_ex;
|
||||
struct extent *iomem_ex;
|
||||
static int ioport_malloc_safe;
|
||||
|
||||
int x86_mem_add_mapping __P((bus_addr_t, bus_size_t,
|
||||
int, bus_space_handle_t *));
|
||||
|
||||
void
|
||||
x86_bus_space_init()
|
||||
{
|
||||
/*
|
||||
* Initialize the I/O port and I/O mem extent maps.
|
||||
* Note: we don't have to check the return value since
|
||||
* creation of a fixed extent map will never fail (since
|
||||
* descriptor storage has already been allocated).
|
||||
*
|
||||
* N.B. The iomem extent manages _all_ physical addresses
|
||||
* on the machine. When the amount of RAM is found, the two
|
||||
* extents of RAM are allocated from the map (0 -> ISA hole
|
||||
* and end of ISA hole -> end of RAM).
|
||||
*/
|
||||
ioport_ex = extent_create("ioport", 0x0, 0xffff, M_DEVBUF,
|
||||
(caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage),
|
||||
EX_NOCOALESCE|EX_NOWAIT);
|
||||
iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
|
||||
(caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
|
||||
EX_NOCOALESCE|EX_NOWAIT);
|
||||
|
||||
/* We are privileged guest os - should have IO privileges. */
|
||||
if (xen_start_info.flags & SIF_PRIVILEGED) {
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_IOPL;
|
||||
op.u.iopl.domain = xen_start_info.dom_id;
|
||||
op.u.iopl.iopl = 1;
|
||||
if (HYPERVISOR_dom0_op(&op) != 0)
|
||||
panic("Unable to obtain IOPL, "
|
||||
"despite being SIF_PRIVILEGED");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86_bus_space_mallocok()
|
||||
{
|
||||
|
||||
ioport_malloc_safe = 1;
|
||||
}
|
||||
|
||||
int
|
||||
x86_memio_map(t, bpa, size, flags, bshp)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t bpa;
|
||||
bus_size_t size;
|
||||
int flags;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
int error;
|
||||
struct extent *ex;
|
||||
|
||||
/*
|
||||
* Pick the appropriate extent map.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
if (flags & BUS_SPACE_MAP_LINEAR)
|
||||
return (EOPNOTSUPP);
|
||||
ex = ioport_ex;
|
||||
} else if (t == X86_BUS_SPACE_MEM)
|
||||
ex = iomem_ex;
|
||||
else
|
||||
panic("x86_memio_map: bad bus space tag");
|
||||
|
||||
/*
|
||||
* Before we go any further, let's make sure that this
|
||||
* region is available.
|
||||
*/
|
||||
error = extent_alloc_region(ex, bpa, size,
|
||||
EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* For I/O space, that's all she wrote.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
*bshp = bpa;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For memory space, map the bus physical address to
|
||||
* a kernel virtual address.
|
||||
*/
|
||||
error = x86_mem_add_mapping(bpa, size,
|
||||
(flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
|
||||
if (error) {
|
||||
if (extent_free(ex, bpa, size, EX_NOWAIT |
|
||||
(ioport_malloc_safe ? EX_MALLOCOK : 0))) {
|
||||
printf("x86_memio_map: pa 0x%lx, size 0x%lx\n",
|
||||
bpa, size);
|
||||
printf("x86_memio_map: can't free region\n");
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
_x86_memio_map(t, bpa, size, flags, bshp)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t bpa;
|
||||
bus_size_t size;
|
||||
int flags;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
|
||||
/*
|
||||
* For I/O space, just fill in the handle.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
if (flags & BUS_SPACE_MAP_LINEAR)
|
||||
return (EOPNOTSUPP);
|
||||
*bshp = bpa;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For memory space, map the bus physical address to
|
||||
* a kernel virtual address.
|
||||
*/
|
||||
return (x86_mem_add_mapping(bpa, size,
|
||||
(flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp));
|
||||
}
|
||||
|
||||
int
|
||||
x86_memio_alloc(t, rstart, rend, size, alignment, boundary, flags,
|
||||
bpap, bshp)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t rstart, rend;
|
||||
bus_size_t size, alignment, boundary;
|
||||
int flags;
|
||||
bus_addr_t *bpap;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
struct extent *ex;
|
||||
u_long bpa;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Pick the appropriate extent map.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
if (flags & BUS_SPACE_MAP_LINEAR)
|
||||
return (EOPNOTSUPP);
|
||||
ex = ioport_ex;
|
||||
} else if (t == X86_BUS_SPACE_MEM)
|
||||
ex = iomem_ex;
|
||||
else
|
||||
panic("x86_memio_alloc: bad bus space tag");
|
||||
|
||||
/*
|
||||
* Sanity check the allocation against the extent's boundaries.
|
||||
*/
|
||||
if (rstart < ex->ex_start || rend > ex->ex_end)
|
||||
panic("x86_memio_alloc: bad region start/end");
|
||||
|
||||
/*
|
||||
* Do the requested allocation.
|
||||
*/
|
||||
error = extent_alloc_subregion(ex, rstart, rend, size, alignment,
|
||||
boundary,
|
||||
EX_FAST | EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0),
|
||||
&bpa);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* For I/O space, that's all she wrote.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
*bshp = *bpap = bpa;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For memory space, map the bus physical address to
|
||||
* a kernel virtual address.
|
||||
*/
|
||||
error = x86_mem_add_mapping(bpa, size,
|
||||
(flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
|
||||
if (error) {
|
||||
if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
|
||||
(ioport_malloc_safe ? EX_MALLOCOK : 0))) {
|
||||
printf("x86_memio_alloc: pa 0x%lx, size 0x%lx\n",
|
||||
bpa, size);
|
||||
printf("x86_memio_alloc: can't free region\n");
|
||||
}
|
||||
}
|
||||
|
||||
*bpap = bpa;
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
x86_mem_add_mapping(bpa, size, cacheable, bshp)
|
||||
bus_addr_t bpa;
|
||||
bus_size_t size;
|
||||
int cacheable;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
u_long pa, endpa;
|
||||
vaddr_t va;
|
||||
pt_entry_t *pte;
|
||||
int32_t cpumask = 0;
|
||||
|
||||
pa = x86_trunc_page(bpa);
|
||||
endpa = x86_round_page(bpa + size);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (endpa <= pa)
|
||||
panic("x86_mem_add_mapping: overflow");
|
||||
#endif
|
||||
|
||||
if (bpa >= IOM_BEGIN && (bpa + size) <= IOM_END) {
|
||||
va = (vaddr_t)ISA_HOLE_VADDR(pa);
|
||||
} else {
|
||||
va = uvm_km_valloc(kernel_map, endpa - pa);
|
||||
if (va == 0)
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
*bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
|
||||
|
||||
for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
|
||||
pmap_kenter_ma(va, pa, VM_PROT_READ | VM_PROT_WRITE);
|
||||
|
||||
/*
|
||||
* PG_N doesn't exist on 386's, so we assume that
|
||||
* the mainboard has wired up device space non-cacheable
|
||||
* on those machines.
|
||||
*
|
||||
* Note that it's not necessary to use atomic ops to
|
||||
* fiddle with the PTE here, because we don't care
|
||||
* about mod/ref information.
|
||||
*
|
||||
* XXX should hand this bit to pmap_kenter_pa to
|
||||
* save the extra invalidate!
|
||||
*
|
||||
* XXX extreme paranoia suggests tlb shootdown belongs here.
|
||||
*/
|
||||
if (pmap_cpu_has_pg_n()) {
|
||||
pte = kvtopte(va);
|
||||
if (cacheable)
|
||||
PTE_CLEARBITS(pte, PG_N);
|
||||
else
|
||||
PTE_SETBITS(pte, PG_N);
|
||||
pmap_tlb_shootdown(pmap_kernel(), va, *pte,
|
||||
&cpumask);
|
||||
}
|
||||
}
|
||||
|
||||
pmap_tlb_shootnow(cpumask);
|
||||
pmap_update(pmap_kernel());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* void _x86_memio_unmap(bus_space_tag bst, bus_space_handle bsh,
|
||||
* bus_size_t size, bus_addr_t *adrp)
|
||||
*
|
||||
* This function unmaps memory- or io-space mapped by the function
|
||||
* _x86_memio_map(). This function works nearly as same as
|
||||
* x86_memio_unmap(), but this function does not ask kernel
|
||||
* built-in extents and returns physical address of the bus space,
|
||||
* for the convenience of the extra extent manager.
|
||||
*/
|
||||
void
|
||||
_x86_memio_unmap(t, bsh, size, adrp)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t size;
|
||||
bus_addr_t *adrp;
|
||||
{
|
||||
u_long va, endva;
|
||||
bus_addr_t bpa;
|
||||
|
||||
/*
|
||||
* Find the correct extent and bus physical address.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
bpa = bsh;
|
||||
} else if (t == X86_BUS_SPACE_MEM) {
|
||||
if (bsh >= atdevbase && (bsh + size) <= (atdevbase + IOM_SIZE)) {
|
||||
bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
|
||||
} else {
|
||||
|
||||
va = x86_trunc_page(bsh);
|
||||
endva = x86_round_page(bsh + size);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (endva <= va) {
|
||||
panic("_x86_memio_unmap: overflow");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __NetBSD_Version__ > 104050000
|
||||
if (pmap_extract(pmap_kernel(), va, &bpa) == FALSE) {
|
||||
panic("_x86_memio_unmap:"
|
||||
" wrong virtual address");
|
||||
}
|
||||
bpa += (bsh & PGOFSET);
|
||||
#else
|
||||
bpa = pmap_extract(pmap_kernel(), va) + (bsh & PGOFSET);
|
||||
#endif
|
||||
|
||||
pmap_kremove(va, endva - va);
|
||||
/*
|
||||
* Free the kernel virtual mapping.
|
||||
*/
|
||||
uvm_km_free(kernel_map, va, endva - va);
|
||||
}
|
||||
} else {
|
||||
panic("_x86_memio_unmap: bad bus space tag");
|
||||
}
|
||||
|
||||
if (adrp != NULL) {
|
||||
*adrp = bpa;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86_memio_unmap(t, bsh, size)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t size;
|
||||
{
|
||||
struct extent *ex;
|
||||
u_long va, endva;
|
||||
bus_addr_t bpa;
|
||||
|
||||
/*
|
||||
* Find the correct extent and bus physical address.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
ex = ioport_ex;
|
||||
bpa = bsh;
|
||||
} else if (t == X86_BUS_SPACE_MEM) {
|
||||
ex = iomem_ex;
|
||||
|
||||
if (bsh >= atdevbase &&
|
||||
(bsh + size) <= (atdevbase + IOM_SIZE)) {
|
||||
bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
va = x86_trunc_page(bsh);
|
||||
endva = x86_round_page(bsh + size);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (endva <= va)
|
||||
panic("x86_memio_unmap: overflow");
|
||||
#endif
|
||||
|
||||
(void) pmap_extract(pmap_kernel(), va, &bpa);
|
||||
bpa += (bsh & PGOFSET);
|
||||
|
||||
pmap_kremove(va, endva - va);
|
||||
/*
|
||||
* Free the kernel virtual mapping.
|
||||
*/
|
||||
uvm_km_free(kernel_map, va, endva - va);
|
||||
} else
|
||||
panic("x86_memio_unmap: bad bus space tag");
|
||||
|
||||
ok:
|
||||
if (extent_free(ex, bpa, size,
|
||||
EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
|
||||
printf("x86_memio_unmap: %s 0x%lx, size 0x%lx\n",
|
||||
(t == X86_BUS_SPACE_IO) ? "port" : "pa", bpa, size);
|
||||
printf("x86_memio_unmap: can't free region\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86_memio_free(t, bsh, size)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t size;
|
||||
{
|
||||
|
||||
/* x86_memio_unmap() does all that we need to do. */
|
||||
x86_memio_unmap(t, bsh, size);
|
||||
}
|
||||
|
||||
int
|
||||
x86_memio_subregion(t, bsh, offset, size, nbshp)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t offset, size;
|
||||
bus_space_handle_t *nbshp;
|
||||
{
|
||||
|
||||
*nbshp = bsh + offset;
|
||||
return (0);
|
||||
}
|
||||
|
||||
paddr_t
|
||||
x86_memio_mmap(t, addr, off, prot, flags)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t addr;
|
||||
off_t off;
|
||||
int prot;
|
||||
int flags;
|
||||
{
|
||||
|
||||
/* Can't mmap I/O space. */
|
||||
if (t == X86_BUS_SPACE_IO)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* "addr" is the base address of the device we're mapping.
|
||||
* "off" is the offset into that device.
|
||||
*
|
||||
* Note we are called for each "page" in the device that
|
||||
* the upper layers want to map.
|
||||
*/
|
||||
return (x86_btop(addr + off));
|
||||
}
|
Loading…
Reference in New Issue