2000-09-29 13:46:07 +00:00
|
|
|
/*
|
|
|
|
* $FreeBSD$
|
|
|
|
*/
|
|
|
|
#ifndef _MACHINE_SMP_H_
|
|
|
|
#define _MACHINE_SMP_H_
|
|
|
|
|
|
|
|
#ifdef _KERNEL
|
|
|
|
|
2010-03-17 00:37:15 +00:00
|
|
|
#define IPI_AST ia64_ipi_ast
|
2011-06-25 02:15:14 +00:00
|
|
|
#define IPI_HARDCLOCK ia64_ipi_hardclock
|
2010-03-17 00:37:15 +00:00
|
|
|
#define IPI_PREEMPT ia64_ipi_preempt
|
|
|
|
#define IPI_RENDEZVOUS ia64_ipi_rndzvs
|
|
|
|
#define IPI_STOP ia64_ipi_stop
|
|
|
|
#define IPI_STOP_HARD ia64_ipi_nmi
|
2000-09-29 13:46:07 +00:00
|
|
|
|
|
|
|
#ifndef LOCORE
|
|
|
|
|
Commit the support for removing cpumask_t and replacing it directly with
cpuset_t objects.
That is going to offer the underlying support for a simple bump of
MAXCPU and then support for number of cpus > 32 (as it is today).
Right now, cpumask_t is an int, 32 bits on all our supported architecture.
cpumask_t on the other side is implemented as an array of longs, and
easilly extendible by definition.
The architectures touched by this commit are the following:
- amd64
- i386
- pc98
- arm
- ia64
- XEN
while the others are still missing.
Userland is believed to be fully converted with the changes contained
here.
Some technical notes:
- This commit may be considered an ABI nop for all the architectures
different from amd64 and ia64 (and sparc64 in the future)
- per-cpu members, which are now converted to cpuset_t, needs to be
accessed avoiding migration, because the size of cpuset_t should be
considered unknown
- size of cpuset_t objects is different from kernel and userland (this is
primirally done in order to leave some more space in userland to cope
with KBI extensions). If you need to access kernel cpuset_t from the
userland please refer to example in this patch on how to do that
correctly (kgdb may be a good source, for example).
- Support for other architectures is going to be added soon
- Only MAXCPU for amd64 is bumped now
The patch has been tested by sbruno and Nicholas Esborn on opteron
4 x 12 pack CPUs. More testing on big SMP is expected to came soon.
pluknet tested the patch with his 8-ways on both amd64 and i386.
Tested by: pluknet, sbruno, gianni, Nicholas Esborn
Reviewed by: jeff, jhb, sbruno
2011-05-05 14:39:14 +00:00
|
|
|
#include <sys/_cpuset.h>
|
|
|
|
|
Improve SMP support:
o Allocate a VHPT per CPU. The VHPT is a hash table that the CPU
uses to look up translations it can't find in the TLB. As such,
the VHPT serves as a level 1 cache (the TLB being a level 0 cache)
and best results are obtained when it's not shared between CPUs.
The collision chain (i.e. the hash bucket) is shared between CPUs,
as all buckets together constitute our collection of PTEs. To
achieve this, the collision chain does not point to the first PTE
in the list anymore, but to a hash bucket head structure. The
head structure contains the pointer to the first PTE in the list,
as well as a mutex to lock the bucket. Thus, each bucket is locked
independently of each other. With at least 1024 buckets in the VHPT,
this provides for sufficiently finei-grained locking to make the
ssolution scalable to large SMP machines.
o Add synchronisation to the lazy FP context switching. We do this
with a seperate per-thread lock. On SMP machines the lazy high FP
context switching without synchronisation caused inconsistent
state, which resulted in a panic. Since the use of the high FP
registers is not common, it's possible that races exist. The ia64
package build has proven to be a good stress test, so this will
get plenty of exercise in the near future.
o Don't use the local ID of the processor we want to send the IPI to
as the argument to ipi_send(). use the struct pcpu pointer instead.
The reason for this is that IPI delivery is unreliable. It has been
observed that sending an IPI to a CPU causes it to receive a stray
external interrupt. As such, we need a way to make the delivery
reliable. The intended solution is to queue requests in the target
CPU's per-CPU structure and use a single IPI to inform the CPU that
there's a new entry in the queue. If that IPI gets lost, the CPU
can check it's queue at any convenient time (such as for each
clock interrupt). This also allows us to send requests to a CPU
without interrupting it, if such would be beneficial.
With these changes SMP is almost working. There are still some random
process crashes and the machine can hang due to having the IPI lost
that deals with the high FP context switch.
The overhead of introducing the hash bucket head structure results
in a performance degradation of about 1% for UP (extra pointer
indirection). This is surprisingly small and is offset by gaining
reasonably/good scalable SMP support.
2005-08-06 20:28:19 +00:00
|
|
|
struct pcpu;
|
|
|
|
|
2011-04-30 20:49:00 +00:00
|
|
|
struct ia64_ap_state {
|
|
|
|
uint64_t as_trace;
|
|
|
|
uint64_t as_pgtbl_pte;
|
|
|
|
uint64_t as_pgtbl_itir;
|
|
|
|
uint64_t as_text_va;
|
|
|
|
uint64_t as_text_pte;
|
|
|
|
uint64_t as_text_itir;
|
|
|
|
uint64_t as_data_va;
|
|
|
|
uint64_t as_data_pte;
|
|
|
|
uint64_t as_data_itir;
|
|
|
|
void *as_kstack;
|
|
|
|
void *as_kstack_top;
|
|
|
|
struct pcpu *as_pcpu;
|
|
|
|
volatile int as_delay;
|
|
|
|
volatile u_int as_awake;
|
|
|
|
volatile u_int as_spin;
|
|
|
|
};
|
|
|
|
|
2010-03-17 00:37:15 +00:00
|
|
|
extern int ia64_ipi_ast;
|
2011-06-25 02:15:14 +00:00
|
|
|
extern int ia64_ipi_hardclock;
|
2010-03-17 00:37:15 +00:00
|
|
|
extern int ia64_ipi_highfp;
|
|
|
|
extern int ia64_ipi_nmi;
|
|
|
|
extern int ia64_ipi_preempt;
|
|
|
|
extern int ia64_ipi_rndzvs;
|
|
|
|
extern int ia64_ipi_stop;
|
|
|
|
extern int ia64_ipi_wakeup;
|
2000-09-29 13:46:07 +00:00
|
|
|
|
2001-10-29 02:16:02 +00:00
|
|
|
void ipi_all_but_self(int ipi);
|
2010-08-06 15:36:59 +00:00
|
|
|
void ipi_cpu(int cpu, u_int ipi);
|
Commit the support for removing cpumask_t and replacing it directly with
cpuset_t objects.
That is going to offer the underlying support for a simple bump of
MAXCPU and then support for number of cpus > 32 (as it is today).
Right now, cpumask_t is an int, 32 bits on all our supported architecture.
cpumask_t on the other side is implemented as an array of longs, and
easilly extendible by definition.
The architectures touched by this commit are the following:
- amd64
- i386
- pc98
- arm
- ia64
- XEN
while the others are still missing.
Userland is believed to be fully converted with the changes contained
here.
Some technical notes:
- This commit may be considered an ABI nop for all the architectures
different from amd64 and ia64 (and sparc64 in the future)
- per-cpu members, which are now converted to cpuset_t, needs to be
accessed avoiding migration, because the size of cpuset_t should be
considered unknown
- size of cpuset_t objects is different from kernel and userland (this is
primirally done in order to leave some more space in userland to cope
with KBI extensions). If you need to access kernel cpuset_t from the
userland please refer to example in this patch on how to do that
correctly (kgdb may be a good source, for example).
- Support for other architectures is going to be added soon
- Only MAXCPU for amd64 is bumped now
The patch has been tested by sbruno and Nicholas Esborn on opteron
4 x 12 pack CPUs. More testing on big SMP is expected to came soon.
pluknet tested the patch with his 8-ways on both amd64 and i386.
Tested by: pluknet, sbruno, gianni, Nicholas Esborn
Reviewed by: jeff, jhb, sbruno
2011-05-05 14:39:14 +00:00
|
|
|
void ipi_selected(cpuset_t cpus, int ipi);
|
Improve SMP support:
o Allocate a VHPT per CPU. The VHPT is a hash table that the CPU
uses to look up translations it can't find in the TLB. As such,
the VHPT serves as a level 1 cache (the TLB being a level 0 cache)
and best results are obtained when it's not shared between CPUs.
The collision chain (i.e. the hash bucket) is shared between CPUs,
as all buckets together constitute our collection of PTEs. To
achieve this, the collision chain does not point to the first PTE
in the list anymore, but to a hash bucket head structure. The
head structure contains the pointer to the first PTE in the list,
as well as a mutex to lock the bucket. Thus, each bucket is locked
independently of each other. With at least 1024 buckets in the VHPT,
this provides for sufficiently finei-grained locking to make the
ssolution scalable to large SMP machines.
o Add synchronisation to the lazy FP context switching. We do this
with a seperate per-thread lock. On SMP machines the lazy high FP
context switching without synchronisation caused inconsistent
state, which resulted in a panic. Since the use of the high FP
registers is not common, it's possible that races exist. The ia64
package build has proven to be a good stress test, so this will
get plenty of exercise in the near future.
o Don't use the local ID of the processor we want to send the IPI to
as the argument to ipi_send(). use the struct pcpu pointer instead.
The reason for this is that IPI delivery is unreliable. It has been
observed that sending an IPI to a CPU causes it to receive a stray
external interrupt. As such, we need a way to make the delivery
reliable. The intended solution is to queue requests in the target
CPU's per-CPU structure and use a single IPI to inform the CPU that
there's a new entry in the queue. If that IPI gets lost, the CPU
can check it's queue at any convenient time (such as for each
clock interrupt). This also allows us to send requests to a CPU
without interrupting it, if such would be beneficial.
With these changes SMP is almost working. There are still some random
process crashes and the machine can hang due to having the IPI lost
that deals with the high FP context switch.
The overhead of introducing the hash bucket head structure results
in a performance degradation of about 1% for UP (extra pointer
indirection). This is surprisingly small and is offset by gaining
reasonably/good scalable SMP support.
2005-08-06 20:28:19 +00:00
|
|
|
void ipi_send(struct pcpu *, int ipi);
|
2000-09-29 13:46:07 +00:00
|
|
|
|
|
|
|
#endif /* !LOCORE */
|
|
|
|
#endif /* _KERNEL */
|
2001-04-27 19:28:25 +00:00
|
|
|
#endif /* !_MACHINE_SMP_H */
|