mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
MFC rev 199893, 199941, 200200 and 200207:
o Eliminate MAXCPU. o Revamp the PCPU structure.
This commit is contained in:
parent
f695ba479e
commit
5b574e433f
10 changed files with 210 additions and 142 deletions
|
|
@ -64,9 +64,9 @@ void
|
|||
pcpu_initclock(void)
|
||||
{
|
||||
|
||||
PCPU_SET(clockadj, 0);
|
||||
PCPU_SET(clock, ia64_get_itc());
|
||||
ia64_set_itm(PCPU_GET(clock) + ia64_clock_reload);
|
||||
PCPU_SET(md.clockadj, 0);
|
||||
PCPU_SET(md.clock, ia64_get_itc());
|
||||
ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload);
|
||||
ia64_set_itv(CLOCK_VECTOR); /* highest priority class */
|
||||
ia64_srlz_d();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ ASSYM(MC_SPECIAL_RNAT, offsetof(mcontext_t, mc_special.rnat));
|
|||
ASSYM(PAGE_SHIFT, PAGE_SHIFT);
|
||||
ASSYM(PAGE_SIZE, PAGE_SIZE);
|
||||
|
||||
ASSYM(PC_CURRENT_PMAP, offsetof(struct pcpu, pc_current_pmap));
|
||||
ASSYM(PC_CURRENT_PMAP, offsetof(struct pcpu, pc_md.current_pmap));
|
||||
ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
|
||||
ASSYM(PC_IDLETHREAD, offsetof(struct pcpu, pc_idlethread));
|
||||
|
||||
|
|
|
|||
|
|
@ -84,28 +84,6 @@ dummy_perf(unsigned long vector, struct trapframe *tf)
|
|||
|
||||
void (*perf_irq)(unsigned long, struct trapframe *) = dummy_perf;
|
||||
|
||||
static unsigned int ints[MAXCPU];
|
||||
SYSCTL_OPAQUE(_debug, OID_AUTO, ints, CTLFLAG_RW, &ints, sizeof(ints), "IU",
|
||||
"");
|
||||
|
||||
static unsigned int clks[MAXCPU];
|
||||
#ifdef SMP
|
||||
SYSCTL_OPAQUE(_debug, OID_AUTO, clks, CTLFLAG_RW, &clks, sizeof(clks), "IU",
|
||||
"");
|
||||
#else
|
||||
SYSCTL_INT(_debug, OID_AUTO, clks, CTLFLAG_RW, clks, 0, "");
|
||||
#endif
|
||||
|
||||
#ifdef SMP
|
||||
static unsigned int asts[MAXCPU];
|
||||
SYSCTL_OPAQUE(_debug, OID_AUTO, asts, CTLFLAG_RW, &asts, sizeof(asts), "IU",
|
||||
"");
|
||||
|
||||
static unsigned int rdvs[MAXCPU];
|
||||
SYSCTL_OPAQUE(_debug, OID_AUTO, rdvs, CTLFLAG_RW, &rdvs, sizeof(rdvs), "IU",
|
||||
"");
|
||||
#endif
|
||||
|
||||
SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics");
|
||||
|
||||
static int adjust_edges = 0;
|
||||
|
|
@ -139,6 +117,8 @@ interrupt(struct trapframe *tf)
|
|||
|
||||
td = curthread;
|
||||
|
||||
PCPU_INC(cnt.v_intr);
|
||||
|
||||
vector = tf->tf_special.ifa;
|
||||
|
||||
next:
|
||||
|
|
@ -149,33 +129,35 @@ interrupt(struct trapframe *tf)
|
|||
* to add it to this switch-like construct.
|
||||
*/
|
||||
if (vector == 0) {
|
||||
PCPU_INC(md.stats.pcs_nextints);
|
||||
inta = ib->ib_inta;
|
||||
printf("ExtINT interrupt: vector=%u\n", (int)inta);
|
||||
if (inta == 15) {
|
||||
PCPU_INC(md.stats.pcs_nstrays);
|
||||
__asm __volatile("mov cr.eoi = r0;; srlz.d");
|
||||
goto stray;
|
||||
}
|
||||
vector = (int)inta;
|
||||
} else if (vector == 15)
|
||||
} else if (vector == 15) {
|
||||
PCPU_INC(md.stats.pcs_nstrays);
|
||||
goto stray;
|
||||
}
|
||||
|
||||
if (vector == CLOCK_VECTOR) {/* clock interrupt */
|
||||
/* CTR0(KTR_INTR, "clock interrupt"); */
|
||||
|
||||
itc = ia64_get_itc();
|
||||
|
||||
PCPU_INC(cnt.v_intr);
|
||||
PCPU_INC(md.stats.pcs_nclks);
|
||||
#ifdef EVCNT_COUNTERS
|
||||
clock_intr_evcnt.ev_count++;
|
||||
#else
|
||||
intrcnt[INTRCNT_CLOCK]++;
|
||||
#endif
|
||||
clks[PCPU_GET(cpuid)]++;
|
||||
|
||||
critical_enter();
|
||||
|
||||
adj = PCPU_GET(clockadj);
|
||||
clk = PCPU_GET(clock);
|
||||
adj = PCPU_GET(md.clockadj);
|
||||
clk = PCPU_GET(md.clock);
|
||||
delta = itc - clk;
|
||||
count = 0;
|
||||
while (delta >= ia64_clock_reload) {
|
||||
|
|
@ -206,33 +188,36 @@ interrupt(struct trapframe *tf)
|
|||
adj = 0;
|
||||
adjust_excess++;
|
||||
}
|
||||
PCPU_SET(clock, clk);
|
||||
PCPU_SET(clockadj, adj);
|
||||
PCPU_SET(md.clock, clk);
|
||||
PCPU_SET(md.clockadj, adj);
|
||||
critical_exit();
|
||||
ia64_srlz_d();
|
||||
|
||||
#ifdef SMP
|
||||
} else if (vector == ipi_vector[IPI_AST]) {
|
||||
asts[PCPU_GET(cpuid)]++;
|
||||
PCPU_INC(md.stats.pcs_nasts);
|
||||
CTR1(KTR_SMP, "IPI_AST, cpuid=%d", PCPU_GET(cpuid));
|
||||
} else if (vector == ipi_vector[IPI_HIGH_FP]) {
|
||||
PCPU_INC(md.stats.pcs_nhighfps);
|
||||
ia64_highfp_save_ipi();
|
||||
} else if (vector == ipi_vector[IPI_RENDEZVOUS]) {
|
||||
rdvs[PCPU_GET(cpuid)]++;
|
||||
PCPU_INC(md.stats.pcs_nrdvs);
|
||||
CTR1(KTR_SMP, "IPI_RENDEZVOUS, cpuid=%d", PCPU_GET(cpuid));
|
||||
enable_intr();
|
||||
smp_rendezvous_action();
|
||||
disable_intr();
|
||||
} else if (vector == ipi_vector[IPI_STOP]) {
|
||||
PCPU_INC(md.stats.pcs_nstops);
|
||||
cpumask_t mybit = PCPU_GET(cpumask);
|
||||
|
||||
savectx(PCPU_PTR(pcb));
|
||||
savectx(PCPU_PTR(md.pcb));
|
||||
atomic_set_int(&stopped_cpus, mybit);
|
||||
while ((started_cpus & mybit) == 0)
|
||||
cpu_spinwait();
|
||||
atomic_clear_int(&started_cpus, mybit);
|
||||
atomic_clear_int(&stopped_cpus, mybit);
|
||||
} else if (vector == ipi_vector[IPI_PREEMPT]) {
|
||||
PCPU_INC(md.stats.pcs_npreempts);
|
||||
CTR1(KTR_SMP, "IPI_PREEMPT, cpuid=%d", PCPU_GET(cpuid));
|
||||
__asm __volatile("mov cr.eoi = r0;; srlz.d");
|
||||
enable_intr();
|
||||
|
|
@ -241,7 +226,7 @@ interrupt(struct trapframe *tf)
|
|||
goto stray;
|
||||
#endif
|
||||
} else {
|
||||
ints[PCPU_GET(cpuid)]++;
|
||||
PCPU_INC(md.stats.pcs_nhwints);
|
||||
atomic_add_int(&td->td_intr_nesting_level, 1);
|
||||
ia64_dispatch_intr(tf, vector);
|
||||
atomic_subtract_int(&td->td_intr_nesting_level, 1);
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
#include <i386/include/specialreg.h>
|
||||
|
||||
SYSCTL_NODE(_machdep, OID_AUTO, cpu, CTLFLAG_RD, 0, "");
|
||||
|
||||
u_int64_t processor_frequency;
|
||||
u_int64_t bus_frequency;
|
||||
u_int64_t itc_frequency;
|
||||
|
|
@ -139,8 +141,6 @@ SYSCTL_STRING(_hw, OID_AUTO, family, CTLFLAG_RD, cpu_family, 0,
|
|||
extern vm_offset_t ksym_start, ksym_end;
|
||||
#endif
|
||||
|
||||
static void cpu_startup(void *);
|
||||
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
|
||||
|
||||
struct msgbuf *msgbufp = NULL;
|
||||
|
||||
|
|
@ -247,9 +247,11 @@ identifycpu(void)
|
|||
}
|
||||
|
||||
static void
|
||||
cpu_startup(dummy)
|
||||
void *dummy;
|
||||
cpu_startup(void *dummy)
|
||||
{
|
||||
char nodename[16];
|
||||
struct pcpu *pc;
|
||||
struct pcpu_stats *pcs;
|
||||
|
||||
/*
|
||||
* Good {morning,afternoon,evening,night}.
|
||||
|
|
@ -302,7 +304,68 @@ cpu_startup(dummy)
|
|||
*/
|
||||
ia64_probe_sapics();
|
||||
ia64_mca_init();
|
||||
|
||||
/*
|
||||
* Create sysctl tree for per-CPU information.
|
||||
*/
|
||||
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
|
||||
snprintf(nodename, sizeof(nodename), "%u", pc->pc_cpuid);
|
||||
sysctl_ctx_init(&pc->pc_md.sysctl_ctx);
|
||||
pc->pc_md.sysctl_tree = SYSCTL_ADD_NODE(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_STATIC_CHILDREN(_machdep_cpu), OID_AUTO, nodename,
|
||||
CTLFLAG_RD, NULL, "");
|
||||
if (pc->pc_md.sysctl_tree == NULL)
|
||||
continue;
|
||||
|
||||
pcs = &pc->pc_md.stats;
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nasts", CTLFLAG_RD, &pcs->pcs_nasts,
|
||||
"Number of IPI_AST interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nclks", CTLFLAG_RD, &pcs->pcs_nclks,
|
||||
"Number of clock interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nextints", CTLFLAG_RD, &pcs->pcs_nextints,
|
||||
"Number of ExtINT interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nhighfps", CTLFLAG_RD, &pcs->pcs_nhighfps,
|
||||
"Number of IPI_HIGH_FP interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nhwints", CTLFLAG_RD, &pcs->pcs_nhwints,
|
||||
"Number of hardware (device) interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"npreempts", CTLFLAG_RD, &pcs->pcs_npreempts,
|
||||
"Number of IPI_PREEMPT interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nrdvs", CTLFLAG_RD, &pcs->pcs_nrdvs,
|
||||
"Number of IPI_RENDEZVOUS interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nstops", CTLFLAG_RD, &pcs->pcs_nstops,
|
||||
"Number of IPI_STOP interrupts");
|
||||
|
||||
SYSCTL_ADD_ULONG(&pc->pc_md.sysctl_ctx,
|
||||
SYSCTL_CHILDREN(pc->pc_md.sysctl_tree), OID_AUTO,
|
||||
"nstrays", CTLFLAG_RD, &pcs->pcs_nstrays,
|
||||
"Number of stray vectors");
|
||||
}
|
||||
}
|
||||
SYSINIT(cpu_startup, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
|
||||
|
||||
void
|
||||
cpu_boot(int howto)
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ void ia64_ap_startup(void);
|
|||
/* Variables used by os_boot_rendez and ia64_ap_startup */
|
||||
struct pcpu *ap_pcpu;
|
||||
void *ap_stack;
|
||||
uint64_t ap_vhpt;
|
||||
volatile int ap_delay;
|
||||
volatile int ap_awake;
|
||||
volatile int ap_spin;
|
||||
|
|
@ -116,13 +115,15 @@ void
|
|||
ia64_ap_startup(void)
|
||||
{
|
||||
volatile struct ia64_interrupt_block *ib = IA64_INTERRUPT_BLOCK;
|
||||
uint64_t vhpt;
|
||||
int vector;
|
||||
|
||||
pcpup = ap_pcpu;
|
||||
ia64_set_k4((intptr_t)pcpup);
|
||||
|
||||
map_vhpt(ap_vhpt);
|
||||
ia64_set_pta(ap_vhpt + (1 << 8) + (pmap_vhpt_log2size << 2) + 1);
|
||||
vhpt = PCPU_GET(md.vhpt);
|
||||
map_vhpt(vhpt);
|
||||
ia64_set_pta(vhpt + (1 << 8) + (pmap_vhpt_log2size << 2) + 1);
|
||||
ia64_srlz_i();
|
||||
|
||||
ap_awake = 1;
|
||||
|
|
@ -225,7 +226,7 @@ cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid)
|
|||
pc = pcpup;
|
||||
|
||||
pc->pc_acpi_id = acpiid;
|
||||
pc->pc_lid = lid;
|
||||
pc->pc_md.lid = lid;
|
||||
all_cpus |= (1UL << cpuid);
|
||||
}
|
||||
|
||||
|
|
@ -239,8 +240,8 @@ cpu_mp_announce()
|
|||
pc = pcpu_find(i);
|
||||
if (pc != NULL) {
|
||||
printf("cpu%d: ACPI Id=%x, SAPIC Id=%x, SAPIC Eid=%x",
|
||||
i, pc->pc_acpi_id, LID_SAPIC_ID(pc->pc_lid),
|
||||
LID_SAPIC_EID(pc->pc_lid));
|
||||
i, pc->pc_acpi_id, LID_SAPIC_ID(pc->pc_md.lid),
|
||||
LID_SAPIC_EID(pc->pc_md.lid));
|
||||
if (i == 0)
|
||||
printf(" (BSP)\n");
|
||||
else
|
||||
|
|
@ -257,13 +258,18 @@ cpu_mp_start()
|
|||
ap_spin = 1;
|
||||
|
||||
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
|
||||
pc->pc_current_pmap = kernel_pmap;
|
||||
pc->pc_md.current_pmap = kernel_pmap;
|
||||
pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask;
|
||||
if (pc->pc_cpuid > 0) {
|
||||
ap_pcpu = pc;
|
||||
pc->pc_md.vhpt = pmap_alloc_vhpt();
|
||||
if (pc->pc_md.vhpt == 0) {
|
||||
printf("SMP: WARNING: unable to allocate VHPT"
|
||||
" for cpu%d", pc->pc_cpuid);
|
||||
continue;
|
||||
}
|
||||
ap_stack = malloc(KSTACK_PAGES * PAGE_SIZE, M_SMP,
|
||||
M_WAITOK);
|
||||
ap_vhpt = pmap_vhpt_base[pc->pc_cpuid];
|
||||
ap_delay = 2000;
|
||||
ap_awake = 0;
|
||||
|
||||
|
|
@ -275,13 +281,13 @@ cpu_mp_start()
|
|||
do {
|
||||
DELAY(1000);
|
||||
} while (--ap_delay > 0);
|
||||
pc->pc_awake = ap_awake;
|
||||
pc->pc_md.awake = ap_awake;
|
||||
|
||||
if (!ap_awake)
|
||||
printf("SMP: WARNING: cpu%d did not wake up\n",
|
||||
pc->pc_cpuid);
|
||||
} else
|
||||
pc->pc_awake = 1;
|
||||
pc->pc_md.awake = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -298,7 +304,7 @@ cpu_mp_unleash(void *dummy)
|
|||
smp_cpus = 0;
|
||||
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
|
||||
cpus++;
|
||||
if (pc->pc_awake) {
|
||||
if (pc->pc_md.awake) {
|
||||
kproc_create(ia64_store_mca_state,
|
||||
(void*)((uintptr_t)pc->pc_cpuid), NULL, 0, 0,
|
||||
"mca %u", pc->pc_cpuid);
|
||||
|
|
@ -361,7 +367,7 @@ ipi_send(struct pcpu *cpu, int ipi)
|
|||
uint64_t vector;
|
||||
|
||||
pipi = __MEMIO_ADDR(ia64_lapic_address |
|
||||
((cpu->pc_lid & LID_SAPIC_MASK) >> 12));
|
||||
((cpu->pc_md.lid & LID_SAPIC_MASK) >> 12));
|
||||
vector = (uint64_t)(ipi_vector[ipi] & 0xff);
|
||||
KASSERT(vector != 0, ("IPI %d is not assigned a vector", ipi));
|
||||
*pipi = vector;
|
||||
|
|
|
|||
|
|
@ -217,8 +217,6 @@ int pmap_vhpt_nbuckets;
|
|||
SYSCTL_INT(_machdep_vhpt, OID_AUTO, nbuckets, CTLFLAG_RD,
|
||||
&pmap_vhpt_nbuckets, 0, "");
|
||||
|
||||
uint64_t pmap_vhpt_base[MAXCPU];
|
||||
|
||||
int pmap_vhpt_log2size = 0;
|
||||
TUNABLE_INT("machdep.vhpt.log2size", &pmap_vhpt_log2size);
|
||||
SYSCTL_INT(_machdep_vhpt, OID_AUTO, log2size, CTLFLAG_RD,
|
||||
|
|
@ -277,6 +275,40 @@ pmap_steal_memory(vm_size_t size)
|
|||
return va;
|
||||
}
|
||||
|
||||
static void
|
||||
pmap_initialize_vhpt(vm_offset_t vhpt)
|
||||
{
|
||||
struct ia64_lpte *pte;
|
||||
u_int i;
|
||||
|
||||
pte = (struct ia64_lpte *)vhpt;
|
||||
for (i = 0; i < pmap_vhpt_nbuckets; i++) {
|
||||
pte[i].pte = 0;
|
||||
pte[i].itir = 0;
|
||||
pte[i].tag = 1UL << 63; /* Invalid tag */
|
||||
pte[i].chain = (uintptr_t)(pmap_vhpt_bucket + i);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SMP
|
||||
MALLOC_DECLARE(M_SMP);
|
||||
|
||||
vm_offset_t
|
||||
pmap_alloc_vhpt(void)
|
||||
{
|
||||
vm_offset_t vhpt;
|
||||
vm_size_t size;
|
||||
|
||||
size = 1UL << pmap_vhpt_log2size;
|
||||
vhpt = (uintptr_t)contigmalloc(size, M_SMP, 0, 0UL, ~0UL, size, 0UL);
|
||||
if (vhpt != 0) {
|
||||
vhpt = IA64_PHYS_TO_RR7(ia64_tpa(vhpt));
|
||||
pmap_initialize_vhpt(vhpt);
|
||||
}
|
||||
return (vhpt);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bootstrap the system enough to run with virtual memory.
|
||||
*/
|
||||
|
|
@ -284,8 +316,7 @@ void
|
|||
pmap_bootstrap()
|
||||
{
|
||||
struct ia64_pal_result res;
|
||||
struct ia64_lpte *pte;
|
||||
vm_offset_t base, limit;
|
||||
vm_offset_t base;
|
||||
size_t size;
|
||||
int i, j, count, ridbits;
|
||||
|
||||
|
|
@ -365,94 +396,52 @@ pmap_bootstrap()
|
|||
;
|
||||
count = i+2;
|
||||
|
||||
/*
|
||||
* Figure out a useful size for the VHPT, based on the size of
|
||||
* physical memory and try to locate a region which is large
|
||||
* enough to contain the VHPT (which must be a power of two in
|
||||
* size and aligned to a natural boundary).
|
||||
* We silently bump up the VHPT size to the minimum size if the
|
||||
* user has set the tunable too small. Likewise, the VHPT size
|
||||
* is silently capped to the maximum allowed.
|
||||
*/
|
||||
TUNABLE_INT_FETCH("machdep.vhpt.log2size", &pmap_vhpt_log2size);
|
||||
if (pmap_vhpt_log2size == 0) {
|
||||
if (pmap_vhpt_log2size == 0)
|
||||
pmap_vhpt_log2size = 20;
|
||||
else if (pmap_vhpt_log2size < 15)
|
||||
pmap_vhpt_log2size = 15;
|
||||
size = 1UL << pmap_vhpt_log2size;
|
||||
while (size < Maxmem * 32) {
|
||||
pmap_vhpt_log2size++;
|
||||
size <<= 1;
|
||||
}
|
||||
} else if (pmap_vhpt_log2size < 15)
|
||||
pmap_vhpt_log2size = 15;
|
||||
if (pmap_vhpt_log2size > 61)
|
||||
else if (pmap_vhpt_log2size > 61)
|
||||
pmap_vhpt_log2size = 61;
|
||||
|
||||
pmap_vhpt_base[0] = 0;
|
||||
base = limit = 0;
|
||||
base = 0;
|
||||
size = 1UL << pmap_vhpt_log2size;
|
||||
while (pmap_vhpt_base[0] == 0) {
|
||||
if (bootverbose)
|
||||
printf("Trying VHPT size 0x%lx\n", size);
|
||||
for (i = 0; i < count; i += 2) {
|
||||
base = (phys_avail[i] + size - 1) & ~(size - 1);
|
||||
limit = base + MAXCPU * size;
|
||||
if (limit <= phys_avail[i+1])
|
||||
/*
|
||||
* VHPT can fit in this region
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if (!phys_avail[i]) {
|
||||
/* Can't fit, try next smaller size. */
|
||||
pmap_vhpt_log2size--;
|
||||
size >>= 1;
|
||||
} else
|
||||
pmap_vhpt_base[0] = IA64_PHYS_TO_RR7(base);
|
||||
for (i = 0; i < count; i += 2) {
|
||||
base = (phys_avail[i] + size - 1) & ~(size - 1);
|
||||
if (base + size <= phys_avail[i+1])
|
||||
break;
|
||||
}
|
||||
if (pmap_vhpt_log2size < 15)
|
||||
panic("Can't find space for VHPT");
|
||||
|
||||
if (bootverbose)
|
||||
printf("Putting VHPT at 0x%lx\n", base);
|
||||
if (!phys_avail[i])
|
||||
panic("Unable to allocate VHPT");
|
||||
|
||||
if (base != phys_avail[i]) {
|
||||
/* Split this region. */
|
||||
if (bootverbose)
|
||||
printf("Splitting [%p-%p]\n", (void *)phys_avail[i],
|
||||
(void *)phys_avail[i+1]);
|
||||
for (j = count; j > i; j -= 2) {
|
||||
phys_avail[j] = phys_avail[j-2];
|
||||
phys_avail[j+1] = phys_avail[j-2+1];
|
||||
}
|
||||
phys_avail[i+1] = base;
|
||||
phys_avail[i+2] = limit;
|
||||
phys_avail[i+2] = base + size;
|
||||
} else
|
||||
phys_avail[i] = limit;
|
||||
phys_avail[i] = base + size;
|
||||
|
||||
base = IA64_PHYS_TO_RR7(base);
|
||||
PCPU_SET(md.vhpt, base);
|
||||
if (bootverbose)
|
||||
printf("VHPT: address=%#lx, size=%#lx\n", base, size);
|
||||
|
||||
pmap_vhpt_nbuckets = size / sizeof(struct ia64_lpte);
|
||||
|
||||
pmap_vhpt_bucket = (void *)pmap_steal_memory(pmap_vhpt_nbuckets *
|
||||
sizeof(struct ia64_bucket));
|
||||
pte = (struct ia64_lpte *)pmap_vhpt_base[0];
|
||||
for (i = 0; i < pmap_vhpt_nbuckets; i++) {
|
||||
pte[i].pte = 0;
|
||||
pte[i].itir = 0;
|
||||
pte[i].tag = 1UL << 63; /* Invalid tag */
|
||||
pte[i].chain = (uintptr_t)(pmap_vhpt_bucket + i);
|
||||
/* Stolen memory is zeroed! */
|
||||
/* Stolen memory is zeroed. */
|
||||
mtx_init(&pmap_vhpt_bucket[i].mutex, "VHPT bucket lock", NULL,
|
||||
MTX_NOWITNESS | MTX_SPIN);
|
||||
}
|
||||
|
||||
for (i = 1; i < MAXCPU; i++) {
|
||||
pmap_vhpt_base[i] = pmap_vhpt_base[i - 1] + size;
|
||||
bcopy((void *)pmap_vhpt_base[i - 1], (void *)pmap_vhpt_base[i],
|
||||
size);
|
||||
}
|
||||
|
||||
map_vhpt(pmap_vhpt_base[0]);
|
||||
ia64_set_pta(pmap_vhpt_base[0] + (1 << 8) +
|
||||
(pmap_vhpt_log2size << 2) + 1);
|
||||
pmap_initialize_vhpt(base);
|
||||
map_vhpt(base);
|
||||
ia64_set_pta(base + (1 << 8) + (pmap_vhpt_log2size << 2) + 1);
|
||||
ia64_srlz_i();
|
||||
|
||||
virtual_avail = VM_MIN_KERNEL_ADDRESS;
|
||||
|
|
@ -466,7 +455,7 @@ pmap_bootstrap()
|
|||
kernel_pmap->pm_rid[i] = 0;
|
||||
kernel_pmap->pm_active = 1;
|
||||
TAILQ_INIT(&kernel_pmap->pm_pvlist);
|
||||
PCPU_SET(current_pmap, kernel_pmap);
|
||||
PCPU_SET(md.current_pmap, kernel_pmap);
|
||||
|
||||
/*
|
||||
* Region 5 is mapped via the vhpt.
|
||||
|
|
@ -551,15 +540,16 @@ static void
|
|||
pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
|
||||
{
|
||||
struct ia64_lpte *pte;
|
||||
int i, vhpt_ofs;
|
||||
struct pcpu *pc;
|
||||
u_int vhpt_ofs;
|
||||
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(current_pmap)),
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)),
|
||||
("invalidating TLB for non-current pmap"));
|
||||
|
||||
vhpt_ofs = ia64_thash(va) - pmap_vhpt_base[PCPU_GET(cpuid)];
|
||||
vhpt_ofs = ia64_thash(va) - PCPU_GET(md.vhpt);
|
||||
critical_enter();
|
||||
for (i = 0; i < MAXCPU; i++) {
|
||||
pte = (struct ia64_lpte *)(pmap_vhpt_base[i] + vhpt_ofs);
|
||||
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
|
||||
pte = (struct ia64_lpte *)(pc->pc_md.vhpt + vhpt_ofs);
|
||||
if (pte->tag == ia64_ttag(va))
|
||||
pte->tag = 1UL << 63;
|
||||
}
|
||||
|
|
@ -591,7 +581,7 @@ static void
|
|||
pmap_invalidate_all(pmap_t pmap)
|
||||
{
|
||||
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(current_pmap)),
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)),
|
||||
("invalidating TLB for non-current pmap"));
|
||||
|
||||
#ifdef SMP
|
||||
|
|
@ -1172,7 +1162,7 @@ pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte, vm_offset_t va,
|
|||
int error;
|
||||
vm_page_t m;
|
||||
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(current_pmap)),
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)),
|
||||
("removing pte for non-current pmap"));
|
||||
|
||||
/*
|
||||
|
|
@ -1340,7 +1330,7 @@ pmap_remove_page(pmap_t pmap, vm_offset_t va)
|
|||
{
|
||||
struct ia64_lpte *pte;
|
||||
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(current_pmap)),
|
||||
KASSERT((pmap == kernel_pmap || pmap == PCPU_GET(md.current_pmap)),
|
||||
("removing page for non-current pmap"));
|
||||
|
||||
pte = pmap_find_vhpt(va);
|
||||
|
|
@ -2251,7 +2241,7 @@ pmap_switch(pmap_t pm)
|
|||
int i;
|
||||
|
||||
critical_enter();
|
||||
prevpm = PCPU_GET(current_pmap);
|
||||
prevpm = PCPU_GET(md.current_pmap);
|
||||
if (prevpm == pm)
|
||||
goto out;
|
||||
if (prevpm != NULL)
|
||||
|
|
@ -2268,7 +2258,7 @@ pmap_switch(pmap_t pm)
|
|||
}
|
||||
atomic_set_32(&pm->pm_active, PCPU_GET(cpumask));
|
||||
}
|
||||
PCPU_SET(current_pmap, pm);
|
||||
PCPU_SET(md.current_pmap, pm);
|
||||
ia64_srlz_d();
|
||||
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include <machine/frame.h>
|
||||
#include <machine/ia64_cpu.h>
|
||||
|
||||
#define KDB_STOPPEDPCB(pc) (&(pc)->pc_pcb)
|
||||
#define KDB_STOPPEDPCB(pc) (&(pc)->pc_md.pcb)
|
||||
|
||||
static __inline void
|
||||
kdb_cpu_clear_singlestep(void)
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(SMP) || defined(KLD_MODULE)
|
||||
#define MAXCPU 4
|
||||
#define MAXCPU 32
|
||||
#else
|
||||
#define MAXCPU 1
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,16 +30,39 @@
|
|||
#ifndef _MACHINE_PCPU_H_
|
||||
#define _MACHINE_PCPU_H_
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/pcb.h>
|
||||
|
||||
struct pcpu_stats {
|
||||
u_long pcs_nasts; /* IPI_AST counter. */
|
||||
u_long pcs_nclks; /* Clock interrupt counter. */
|
||||
u_long pcs_nextints; /* ExtINT counter. */
|
||||
u_long pcs_nhighfps; /* IPI_HIGH_FP counter. */
|
||||
u_long pcs_nhwints; /* Hardware int. counter. */
|
||||
u_long pcs_npreempts; /* IPI_PREEMPT counter. */
|
||||
u_long pcs_nrdvs; /* IPI_RENDEZVOUS counter. */
|
||||
u_long pcs_nstops; /* IPI_STOP counter. */
|
||||
u_long pcs_nstrays; /* Stray interrupt counter. */
|
||||
};
|
||||
|
||||
struct pcpu_md {
|
||||
struct pcb pcb; /* Used by IPI_STOP */
|
||||
struct pmap *current_pmap; /* active pmap */
|
||||
vm_offset_t vhpt; /* Address of VHPT */
|
||||
uint64_t lid; /* local CPU ID */
|
||||
uint64_t clock; /* Clock counter. */
|
||||
uint64_t clockadj; /* Clock adjust. */
|
||||
uint32_t awake:1; /* CPU is awake? */
|
||||
struct pcpu_stats stats; /* Interrupt stats. */
|
||||
#ifdef _KERNEL
|
||||
struct sysctl_ctx_list sysctl_ctx;
|
||||
struct sysctl_oid *sysctl_tree;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define PCPU_MD_FIELDS \
|
||||
struct pcb pc_pcb; /* Used by IPI_STOP */ \
|
||||
struct pmap *pc_current_pmap; /* active pmap */ \
|
||||
uint64_t pc_lid; /* local CPU ID */ \
|
||||
uint64_t pc_clock; /* Clock counter. */ \
|
||||
uint64_t pc_clockadj; /* Clock adjust. */ \
|
||||
uint32_t pc_awake:1; /* CPU is awake? */ \
|
||||
uint32_t pc_acpi_id /* ACPI CPU id. */
|
||||
uint32_t pc_acpi_id; /* ACPI CPU id. */ \
|
||||
struct pcpu_md pc_md /* MD fields. */
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ extern int pmap_vhpt_log2size;
|
|||
#define pmap_unmapbios(va, sz) pmap_unmapdev(va, sz)
|
||||
|
||||
vm_offset_t pmap_steal_memory(vm_size_t);
|
||||
vm_offset_t pmap_alloc_vhpt(void);
|
||||
void pmap_bootstrap(void);
|
||||
void pmap_kenter(vm_offset_t va, vm_offset_t pa);
|
||||
vm_paddr_t pmap_kextract(vm_offset_t va);
|
||||
|
|
|
|||
Loading…
Reference in a new issue