diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2020-11-29 17:43:22 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2020-11-29 17:43:22 +0100 |
commit | 1d93a5628adc0f08463fe4272dc88fb0f61e631d (patch) | |
tree | b96cb74f50ab891af2fc72ebaf0d8ac6309ae385 /sys/src/9/pc/devarch.c | |
parent | 32a5ff9658cfa2d0d15cecf3b2a27be6b0742227 (diff) |
pc, pc64, xen: rewrite interrupt handling code
This implements proper intrdisable() support for all
interrupt controllers.
For enable, (*arch->intrassign)(Vctl*) fills in the
Vctl.enable and Vctl.disable pointers with the
appropriate routines and returns the assigned
vector number.
Once the Vctl struct has been linked to its vector
chain, Vctl.enable(Vctl*, shared) gets called with a
flag if the vector has been already enabled (shared).
This order is important here as enabling the interrupt
on the controller before we have linked the chain can
cause spurious interrupts, expecially on mp system
where the interrupt can target a different cpu than
the caller of intrenable().
The intrdisable() case is the other way around.
We first disable the interrupt on the controller
and after that unlink the Vctl from the chain.
On a multiprocessor, the xfree() of the Vctl struct
is delayed to avoid freeing it while it is still
in use by another cpu.
The xen port now also uses pc/irq.c which has been
made generic enougth to handle xen's irq scheme.
Also, archgeneric is now a separate file to avoid
pulling in dependencies from the 8259 interrupt
controller code.
Diffstat (limited to 'sys/src/9/pc/devarch.c')
-rw-r--r-- | sys/src/9/pc/devarch.c | 89 |
1 files changed, 34 insertions, 55 deletions
diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c index cc14b394b..6617d3e7b 100644 --- a/sys/src/9/pc/devarch.c +++ b/sys/src/9/pc/devarch.c @@ -324,31 +324,6 @@ nop(void) { } -void -archreset(void) -{ - i8042reset(); - - /* - * Often the BIOS hangs during restart if a conventional 8042 - * warm-boot sequence is tried. The following is Intel specific and - * seems to perform a cold-boot, but at least it comes back. - * And sometimes there is no keyboard... - * - * The reset register (0xcf9) is usually in one of the bridge - * chips. The actual location and sequence could be extracted from - * ACPI but why bother, this is the end of the line anyway. - */ - print("Takes a licking and keeps on ticking...\n"); - *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ - outb(0xcf9, 0x02); - outb(0xcf9, 0x06); - - print("can't reset\n"); - for(;;) - idle(); -} - /* * 386 has no compare-and-swap instruction. * Run it with interrupts turned off instead. @@ -380,25 +355,6 @@ int (*cmpswap)(long*, long, long) = cmpswap386; PCArch* arch; extern PCArch* knownarch[]; -PCArch archgeneric = { -.id= "generic", -.ident= 0, -.reset= archreset, -.serialpower= unimplemented, -.modempower= unimplemented, - -.intrinit= i8259init, -.intrenable= i8259enable, -.intrvecno= i8259vecno, -.intrdisable= i8259disable, -.intron= i8259on, -.introff= i8259off, - -.clockenable= i8253enable, -.fastclock= i8253read, -.timerset= i8253timerset, -}; - typedef struct X86type X86type; struct X86type { int family; @@ -912,26 +868,22 @@ archinit(void) { PCArch **p; - arch = &archgeneric; + arch = knownarch[0]; for(p = knownarch; *p != nil; p++){ if((*p)->ident != nil && (*p)->ident() == 0){ arch = *p; break; } } - if(arch != &archgeneric){ + if(arch != knownarch[0]){ if(arch->id == nil) - arch->id = archgeneric.id; + arch->id = knownarch[0]->id; if(arch->reset == nil) - arch->reset = archgeneric.reset; - if(arch->serialpower == nil) - arch->serialpower = archgeneric.serialpower; - if(arch->modempower == nil) - arch->modempower = archgeneric.modempower; + arch->reset = knownarch[0]->reset; if(arch->intrinit == nil) - arch->intrinit = archgeneric.intrinit; - if(arch->intrenable == nil) - arch->intrenable = archgeneric.intrenable; + arch->intrinit = knownarch[0]->intrinit; + if(arch->intrassign == nil) + arch->intrassign = knownarch[0]->intrassign; } /* @@ -1100,6 +1052,33 @@ dumpmcregs(void) } } +static void +nmihandler(Ureg *ureg, void*) +{ + iprint("cpu%d: nmi PC %#p, status %ux\n", + m->machno, ureg->pc, inb(0x61)); + while(m->machno != 0) + ; +} + +void +nmienable(void) +{ + int x; + + trapenable(VectorNMI, nmihandler, nil, "nmi"); + + /* + * Hack: should be locked with NVRAM access. + */ + outb(0x70, 0x80); /* NMI latch clear */ + outb(0x70, 0); + + x = inb(0x61) & 0x07; /* Enable NMI */ + outb(0x61, 0x0C|x); + outb(0x61, x); +} + void setupwatchpts(Proc *pr, Watchpt *wp, int nwp) { |