freebsd-nq/sys/i386/include/smp.h
Peter Wemm f1b665c8fe Revive backed out pmap related changes from Feb 2002. The highlights are:
- It actually works this time, honest!
- Fine grained TLB shootdowns for SMP on i386.  IPI's are very expensive,
  so try and optimize things where possible.
- Introduce ranged shootdowns that can be done as a single IPI.
- PG_G support for i386
- Specific-cpu targeted shootdowns.  For example, there is no sense in
  globally purging the TLB cache for where we are stealing a page from
  the local unshared process on the local cpu.  Use pm_active to track
  this.
- Add some instrumentation for the tlb shootdown code.
- Rip out SMP code from <machine/cpufunc.h>
- Try and fix some very bogus PG_G and PG_PS interactions that were bad
  enough to cause vm86 bios calls to break.  vm86 depended on our existing
  bugs and this was the cause of the VESA panics last time.
- Fix the silly one-line error that caused the 'panic: bad pte' last time.
- Fix a couple of other silly one-line errors that should have caused more
  pain than they did.

Some more work is needed:
- pmap_{zero,copy}_page[_idle].  These can be done without IPI's if we
  have a hook in cpu_switch.
- The IPI handlers need some cleanup.  I have a bogus %ds load that can
  be avoided.
- APTD handling is rather bogus and appears to be a large source of
  global TLB IPI shootdowns for no really good reason.

I see speedups of between 1.5% and ~4% on buildworlds in a while 1 loop.
I expect to see a bigger difference when there is significant pageout
activity or the system otherwise has memory shortages.

I have backed out a few optimizations that I had been using over the last
few days in order to be a little more conservative.  I'll revisit these
again over the next few days as the dust settles.

New option:  DISABLE_PG_G - In case I missed something.
2002-07-12 07:56:11 +00:00

158 lines
4.4 KiB
C

/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $FreeBSD$
*
*/
#ifndef _MACHINE_SMP_H_
#define _MACHINE_SMP_H_
#ifdef _KERNEL
#if defined(SMP) && defined(I386_CPU) && !defined(COMPILING_LINT)
#error SMP not supported with I386_CPU
#endif
#if defined(SMP) && !defined(APIC_IO)
# error APIC_IO required for SMP, add "options APIC_IO" to your config file.
#endif /* SMP && !APIC_IO */
#if defined(SMP) || defined(APIC_IO)
#ifndef LOCORE
/*
* For sending values to POST displays.
* XXX FIXME: where does this really belong, isa.h/isa.c perhaps?
*/
extern int current_postcode; /** XXX currently in mp_machdep.c */
#define POSTCODE(X) current_postcode = (X), \
outb(0x80, current_postcode)
#define POSTCODE_LO(X) current_postcode &= 0xf0, \
current_postcode |= ((X) & 0x0f), \
outb(0x80, current_postcode)
#define POSTCODE_HI(X) current_postcode &= 0x0f, \
current_postcode |= (((X) << 4) & 0xf0), \
outb(0x80, current_postcode)
#include <sys/bus.h> /* XXX */
#include <machine/apic.h>
#include <machine/frame.h>
#include <i386/isa/icu.h>
#include <i386/isa/intr_machdep.h>
/*
* Interprocessor interrupts for SMP.
*/
#define IPI_INVLTLB XINVLTLB_OFFSET
#define IPI_INVLPG XINVLPG_OFFSET
#define IPI_INVLRNG XINVLRNG_OFFSET
#define IPI_RENDEZVOUS XRENDEZVOUS_OFFSET
#define IPI_AST XCPUAST_OFFSET
#define IPI_STOP XCPUSTOP_OFFSET
#define IPI_HARDCLOCK XHARDCLOCK_OFFSET
#define IPI_STATCLOCK XSTATCLOCK_OFFSET
/* global data in mpboot.s */
extern int bootMP_size;
/* functions in mpboot.s */
void bootMP(void);
/* global data in mp_machdep.c */
extern int bsp_apic_ready;
extern int mp_naps;
extern int mp_nbusses;
extern int mp_napics;
extern int mp_picmode;
extern int boot_cpu_id;
extern vm_offset_t cpu_apic_address;
extern vm_offset_t io_apic_address[];
extern u_int32_t cpu_apic_versions[];
extern u_int32_t *io_apic_versions;
extern int cpu_num_to_apic_id[];
extern int io_num_to_apic_id[];
extern int apic_id_to_logical[];
#define APIC_INTMAPSIZE 32
struct apic_intmapinfo {
int ioapic;
int int_pin;
volatile void *apic_address;
int redirindex;
};
extern struct apic_intmapinfo int_to_apicintpin[];
extern struct pcb stoppcbs[];
/* functions in mp_machdep.c */
void i386_mp_probe(void);
u_int mp_bootaddress(u_int);
u_int isa_apic_mask(u_int);
int isa_apic_irq(int);
int pci_apic_irq(int, int, int);
int apic_irq(int, int);
int next_apic_irq(int);
int undirect_isa_irq(int);
int undirect_pci_irq(int);
int apic_bus_type(int);
int apic_src_bus_id(int, int);
int apic_src_bus_irq(int, int);
int apic_int_type(int, int);
int apic_trigger(int, int);
int apic_polarity(int, int);
void assign_apic_irq(int apic, int intpin, int irq);
void revoke_apic_irq(int irq);
void bsp_apic_configure(void);
void init_secondary(void);
void forward_statclock(void);
void forwarded_statclock(struct trapframe frame);
void forward_hardclock(void);
void forwarded_hardclock(struct trapframe frame);
void ipi_selected(u_int cpus, u_int ipi);
void ipi_all(u_int ipi);
void ipi_all_but_self(u_int ipi);
void ipi_self(u_int ipi);
#ifdef APIC_INTR_REORDER
void set_lapic_isrloc(int, int);
#endif /* APIC_INTR_REORDER */
void smp_invlpg(vm_offset_t addr);
void smp_masked_invlpg(u_int mask, vm_offset_t addr);
void smp_invlpg_range(vm_offset_t startva, vm_offset_t endva);
void smp_masked_invlpg_range(u_int mask, vm_offset_t startva,
vm_offset_t endva);
void smp_invltlb(void);
void smp_masked_invltlb(u_int mask);
/* global data in mpapic.c */
extern volatile lapic_t lapic;
extern volatile ioapic_t **ioapic;
/* functions in mpapic.c */
void apic_dump(char*);
void apic_initialize(void);
void imen_dump(void);
int apic_ipi(int, int, int);
int selected_apic_ipi(u_int, int, int);
int io_apic_setup(int);
void io_apic_setup_intpin(int, int);
void io_apic_set_id(int, int);
int io_apic_get_id(int);
int ext_int_setup(int, int);
void set_apic_timer(int);
int read_apic_timer(void);
void u_sleep(int);
u_int io_apic_read(int, int);
void io_apic_write(int, int, u_int);
#endif /* !LOCORE */
#endif /* SMP && !APIC_IO */
#endif /* _KERNEL */
#endif /* _MACHINE_SMP_H_ */