Some code churn:

o   Eliminate IA64_PHYS_TO_RR6 and change all places where the macro is used
    by calling either bus_space_map() or pmap_mapdev().
o   Implement bus_space_map() in terms of pmap_mapdev() and implement
    bus_space_unmap() in terms of pmap_unmapdev().
o   Have ia64_pib hold the uncached virtual address of the processor interrupt
    block throughout the kernel's life and access the elements of the PIB
    through this structure pointer.

This is a non-functional change with the exception of using ia64_ld1() and
ia64_st8() to write to the PIB. We were still using assignments, for which
the compiler generates semaphore reads -- which cause undefined behaviour
for uncacheable memory. Note also that the memory barriers in ipi_send() are
critical for proper functioning.

With all the mapping of uncached memory done by pmap_mapdev(), we can keep
track of the translations and wire them in the CPU. This then eliminates
the need to reserve a whole region for uncached I/O and it eliminates
translation traps for device I/O accesses.
This commit is contained in:
Marcel Moolenaar 2010-02-14 16:56:24 +00:00
parent 12fefae25c
commit 26279767e4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203883
13 changed files with 86 additions and 70 deletions

View File

@ -31,8 +31,6 @@
#include <machine/md_var.h>
extern u_int64_t ia64_lapic_address;
struct sapic *sapic_create(int, int, u_int64_t);
static void
@ -150,7 +148,7 @@ ia64_probe_sapics(void)
/* Save the address of the processor interrupt block. */
if (bootverbose)
printf("\tLocal APIC address=0x%x\n", table->Address);
ia64_lapic_address = table->Address;
ia64_lapic_addr = table->Address;
end = (char *)table + table->Header.Length;
p = (char *)(table + 1);
@ -172,7 +170,7 @@ ia64_probe_sapics(void)
case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: {
ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic =
(ACPI_MADT_LOCAL_APIC_OVERRIDE *)entry;
ia64_lapic_address = lapic->Address;
ia64_lapic_addr = lapic->Address;
break;
}

View File

@ -29,12 +29,33 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <machine/bus.h>
#include <vm/vm.h>
#include <vm/pmap.h>
extern u_long ia64_port_base;
#define __PIO_ADDR(port) \
(void *)(ia64_port_base | (((port) & 0xfffc) << 10) | ((port) & 0xFFF))
int
bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size,
int flags __unused, bus_space_handle_t *bshp)
{
*bshp = (__predict_false(bst == IA64_BUS_SPACE_IO))
? addr : (uintptr_t)pmap_mapdev(addr, size);
return (0);
}
void
bus_space_unmap(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t size)
{
pmap_unmapdev(bsh, size);
}
uint8_t
bus_space_read_io_1(u_long port)
{

View File

@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$");
#include <machine/bootinfo.h>
#include <machine/efi.h>
#include <machine/sal.h>
#include <vm/vm.h>
#include <vm/pmap.h>
extern uint64_t ia64_call_efi_physical(uint64_t, uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t);
@ -123,8 +125,8 @@ efi_boot_minimal(uint64_t systbl)
md->md_virt =
(void *)IA64_PHYS_TO_RR7(md->md_phys);
else if (md->md_attr & EFI_MD_ATTR_UC)
md->md_virt =
(void *)IA64_PHYS_TO_RR6(md->md_phys);
md->md_virt = pmap_mapdev(md->md_phys,
md->md_pages * EFI_PAGE_SIZE);
}
md = efi_md_next(md);
}

View File

@ -106,7 +106,6 @@ void
interrupt(struct trapframe *tf)
{
struct thread *td;
volatile struct ia64_interrupt_block *ib = IA64_INTERRUPT_BLOCK;
uint64_t adj, clk, itc;
int64_t delta;
u_int vector;
@ -128,7 +127,7 @@ interrupt(struct trapframe *tf)
*/
if (vector == 0) {
PCPU_INC(md.stats.pcs_nextints);
inta = ib->ib_inta;
inta = ia64_ld1(&ia64_pib->ib_inta);
if (inta == 15) {
PCPU_INC(md.stats.pcs_nstrays);
__asm __volatile("mov cr.eoi = r0;; srlz.d");

View File

@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
#include <machine/efi.h>
#include <machine/elf.h>
#include <machine/fpu.h>
#include <machine/intr.h>
#include <machine/mca.h>
#include <machine/md_var.h>
#include <machine/mutex.h>
@ -134,6 +135,10 @@ struct fpswa_iface *fpswa_iface;
u_int64_t ia64_pal_base;
u_int64_t ia64_port_base;
u_int64_t ia64_lapic_addr = PAL_PIB_DEFAULT_ADDR;
struct ia64_pib *ia64_pib;
static int ia64_sync_icache_needed;
char machine[] = MACHINE;
@ -308,6 +313,8 @@ cpu_startup(void *dummy)
* information.
*/
ia64_probe_sapics();
ia64_pib = pmap_mapdev(ia64_lapic_addr, sizeof(*ia64_pib));
ia64_mca_init();
/*
@ -677,7 +684,8 @@ ia64_init(void)
for (md = efi_md_first(); md != NULL; md = efi_md_next(md)) {
switch (md->md_type) {
case EFI_MD_TYPE_IOPORT:
ia64_port_base = IA64_PHYS_TO_RR6(md->md_phys);
ia64_port_base = (uintptr_t)pmap_mapdev(md->md_phys,
md->md_pages * EFI_PAGE_SIZE);
break;
case EFI_MD_TYPE_PALCODE:
ia64_pal_base = md->md_phys;

View File

@ -68,8 +68,9 @@ MALLOC_DEFINE(M_SMP, "SMP", "SMP related allocations");
void ia64_ap_startup(void);
#define LID_SAPIC_ID(x) ((int)((x) >> 24) & 0xff)
#define LID_SAPIC_EID(x) ((int)((x) >> 16) & 0xff)
#define LID_SAPIC(x) ((u_int)((x) >> 16))
#define LID_SAPIC_ID(x) ((u_int)((x) >> 24) & 0xff)
#define LID_SAPIC_EID(x) ((u_int)((x) >> 16) & 0xff)
#define LID_SAPIC_SET(id,eid) (((id & 0xff) << 8 | (eid & 0xff)) << 16);
#define LID_SAPIC_MASK 0xffff0000UL
@ -114,7 +115,6 @@ ia64_store_mca_state(void* arg)
void
ia64_ap_startup(void)
{
volatile struct ia64_interrupt_block *ib = IA64_INTERRUPT_BLOCK;
uint64_t vhpt;
int vector;
@ -153,7 +153,7 @@ ia64_ap_startup(void)
while (vector != 15) {
ia64_srlz_d();
if (vector == 0)
vector = (int)ib->ib_inta;
vector = (int)ia64_ld1(&ia64_pib->ib_inta);
ia64_set_eoi(0);
ia64_srlz_d();
vector = ia64_get_ivr();
@ -363,16 +363,18 @@ ipi_all_but_self(int ipi)
void
ipi_send(struct pcpu *cpu, int ipi)
{
volatile uint64_t *pipi;
uint64_t vector;
u_int lid;
uint8_t vector;
pipi = (void *)IA64_PHYS_TO_RR6(ia64_lapic_address |
((cpu->pc_md.lid & LID_SAPIC_MASK) >> 12));
vector = (uint64_t)(ipi_vector[ipi] & 0xff);
lid = LID_SAPIC(cpu->pc_md.lid);
vector = ipi_vector[ipi];
KASSERT(vector != 0, ("IPI %d is not assigned a vector", ipi));
*pipi = vector;
CTR3(KTR_SMP, "ipi_send(%p, %ld), cpuid=%d", pipi, vector,
PCPU_GET(cpuid));
ia64_mf();
ia64_st8(&(ia64_pib->ib_ipi[lid][0]), vector);
ia64_mf_a();
CTR4(KTR_SMP, "ipi_send(%p, %ld): cpuid=%d, vector=%u", cpu, ipi,
PCPU_GET(cpuid), vector);
}
SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);

View File

@ -2145,9 +2145,12 @@ pmap_remove_write(vm_page_t m)
* NOT real memory.
*/
void *
pmap_mapdev(vm_offset_t pa, vm_size_t size)
pmap_mapdev(vm_paddr_t pa, vm_size_t size)
{
return (void*) IA64_PHYS_TO_RR6(pa);
vm_offset_t va;
va = pa | IA64_RR_BASE(6);
return ((void *)va);
}
/*
@ -2156,7 +2159,6 @@ pmap_mapdev(vm_offset_t pa, vm_size_t size)
void
pmap_unmapdev(vm_offset_t va, vm_size_t size)
{
return;
}
/*

View File

@ -42,6 +42,9 @@
#include <machine/sapicreg.h>
#include <machine/sapicvar.h>
#include <vm/vm.h>
#include <vm/pmap.h>
static MALLOC_DEFINE(M_SAPIC, "sapic", "I/O SAPIC devices");
static int sysctl_machdep_apic(SYSCTL_HANDLER_ARGS);
@ -52,8 +55,6 @@ SYSCTL_OID(_machdep, OID_AUTO, apic, CTLTYPE_STRING|CTLFLAG_RD,
struct sapic *ia64_sapics[16]; /* XXX make this resizable */
int ia64_sapic_count;
u_int64_t ia64_lapic_address = PAL_PIB_DEFAULT_ADDR;
struct sapic_rte {
u_int64_t rte_vector :8;
u_int64_t rte_delivery_mode :3;
@ -165,7 +166,7 @@ sapic_create(u_int id, u_int base, u_int64_t address)
sa->sa_id = id;
sa->sa_base = base;
sa->sa_registers = IA64_PHYS_TO_RR6(address);
sa->sa_registers = (uintptr_t)pmap_mapdev(address, 1048576);
mtx_init(&sa->sa_mtx, "I/O SAPIC lock", NULL, MTX_SPIN);

View File

@ -132,28 +132,14 @@
/*
* Map a region of device bus space into CPU virtual address space.
* Map and unmap a region of device bus space into CPU virtual address space.
*/
static __inline int
bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size __unused,
int flags __unused, bus_space_handle_t *bshp)
{
*bshp = (__predict_false(bst == IA64_BUS_SPACE_IO))
? addr : IA64_PHYS_TO_RR6(addr);
return (0);
}
/*
* Unmap a region of device bus space.
*/
static __inline void
bus_space_unmap(bus_space_tag_t bst __unused, bus_space_handle_t bsh __unused,
bus_size_t size __unused)
{
}
int
bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_handle_t *);
void
bus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t size);
/*
* Get a new handle for a subregion of an already-mapped area of bus space.

View File

@ -1,4 +1,5 @@
/*-
* Copyright (c) 2007-2010 Marcel Moolenaar
* Copyright (c) 1998 Doug Rabson
* All rights reserved.
*
@ -27,26 +28,23 @@
*/
#ifndef _MACHINE_INTR_H_
#define _MACHINE_INTR_H_
#define _MACHINE_INTR_H_
/*
* Layout of the Processor Interrupt Block.
*/
struct ia64_interrupt_block
struct ia64_pib
{
u_int64_t ib_ipi[0x20000]; /* 1Mb of IPI interrupts */
u_int8_t ib_reserved1[0xe0000];
u_int8_t ib_inta; /* Generate INTA cycle */
u_int8_t ib_reserved2[7];
u_int8_t ib_xtp; /* XTP cycle */
u_int8_t ib_reserved3[7];
u_int8_t ib_reserved4[0x1fff0];
uint64_t ib_ipi[65536][2]; /* 64K-way IPIs (1MB area). */
uint8_t _rsvd1[0xe0000];
uint8_t ib_inta; /* Generate INTA cycle. */
uint8_t _rsvd2[7];
uint8_t ib_xtp; /* External Task Priority. */
uint8_t _rsvd3[7];
uint8_t _rsvd4[0x1fff0];
};
extern u_int64_t ia64_lapic_address;
#define IA64_INTERRUPT_BLOCK \
(struct ia64_interrupt_block *)IA64_PHYS_TO_RR6(ia64_lapic_address)
extern struct ia64_pib *ia64_pib;
int ia64_setup_intr(const char *name, int irq, driver_filter_t filter,
driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep);

View File

@ -49,7 +49,7 @@ struct ia64_fdesc {
#define IA64_CFM_RRB_FR(x) (((x) >> 25) & 0x7f)
#define IA64_CFM_RRB_PR(x) (((x) >> 32) & 0x3f)
/* Concenience function (inline) to adjust backingstore pointers. */
/* Convenience function (inline) to adjust backingstore pointers. */
static __inline uint64_t
ia64_bsp_adjust(uint64_t bsp, int nslots)
{
@ -60,22 +60,22 @@ ia64_bsp_adjust(uint64_t bsp, int nslots)
#ifdef _KERNEL
extern char sigcode[];
extern char esigcode[];
extern int szsigcode;
extern long Maxmem;
struct _special;
struct fpreg;
struct reg;
struct thread;
struct trapframe;
/*
* Return value from ia64_init. Describes stack to switch to.
*/
struct ia64_init_return {
uint64_t bspstore;
uint64_t sp;
};
extern uint64_t ia64_lapic_addr;
extern long Maxmem;
void busdma_swi(void);
int copyout_regstack(struct thread *, uint64_t *, uint64_t *);
void cpu_mp_add(u_int, u_int, u_int);

View File

@ -132,7 +132,7 @@ vm_paddr_t pmap_kextract(vm_offset_t va);
void pmap_kremove(vm_offset_t);
void pmap_setdevram(unsigned long long basea, vm_offset_t sizea);
int pmap_uses_prom_console(void);
void *pmap_mapdev(vm_offset_t, vm_size_t);
void *pmap_mapdev(vm_paddr_t, vm_size_t);
void pmap_unmapdev(vm_offset_t, vm_size_t);
unsigned *pmap_pte(pmap_t, vm_offset_t) __pure2;
void pmap_set_opt (unsigned *);

View File

@ -132,7 +132,6 @@
#define IA64_RR_BASE(n) (((u_int64_t) (n)) << 61)
#define IA64_RR_MASK(x) ((x) & ((1L << 61) - 1))
#define IA64_PHYS_TO_RR6(x) ((x) | IA64_RR_BASE(6))
#define IA64_PHYS_TO_RR7(x) ((x) | IA64_RR_BASE(7))
/*