Skip to content

Commit b30d6e7

Browse files
committed
PLACEHOLDER FOR ALT
THIS SHOULD NOT BE BROUGHT INTO FREEBSD. This is simply a placeholder to keep the previous commit in a handy state. Mostly a demonstration of a more minimal approach which doesn't emulate the existing quite as closely.
1 parent 4e88acc commit b30d6e7

File tree

9 files changed

+103
-47
lines changed

9 files changed

+103
-47
lines changed

sys/x86/include/interrupt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ typedef struct intsrc interrupt_t;
4343

4444
DECLARE_CLASS(pic_base_class);
4545

46+
typedef struct { device_t next, prev; } pic_base_softc_t;
47+
4648
/*
4749
* Values used in determining the allocation of IRQ values among
4850
* different types of I/O interrupts. These values are used as

sys/x86/isa/atpic.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,15 @@ inthand_t
107107
}
108108

109109
struct atpic {
110+
pic_base_softc_t pic_base_softc;
110111
device_t at_pic;
111112
int at_ioaddr;
112113
int at_irqbase;
113114
uint8_t at_intbase;
114115
uint8_t at_imen;
115116
};
117+
_Static_assert(offsetof(struct atpic, pic_base_softc) == 0,
118+
".pic_base_softc misaligned from structure!");
116119

117120
struct atpic_intsrc {
118121
struct intsrc at_intsrc;
@@ -125,9 +128,10 @@ struct atpic_intsrc {
125128

126129
static pic_register_sources_t atpic_register_sources;
127130
static intr_event_post_ithread_t atpic_enable_source;
128-
static intr_event_pre_ithread_t atpic_disable_intr;
131+
static intr_event_pre_ithread_t atpic_disable_source;
129132
static intr_event_post_filter_t atpic_eoi;
130133
static pic_enable_intr_t atpic_enable_intr;
134+
static pic_disable_intr_t atpic_disable_intr;
131135
static pic_resume_t atpic_resume;
132136
static pic_source_pending_t atpic_source_pending;
133137
static pic_config_intr_t atpic_config_intr;
@@ -149,7 +153,7 @@ static const device_method_t atpic_methods[] = {
149153
/* Interrupt event interface */
150154
DEVMETHOD(intr_event_post_filter, atpic_eoi),
151155
DEVMETHOD(intr_event_post_ithread, atpic_enable_source),
152-
DEVMETHOD(intr_event_pre_ithread, atpic_disable_intr),
156+
DEVMETHOD(intr_event_pre_ithread, atpic_disable_source),
153157

154158
/* Interrupt controller interface */
155159
DEVMETHOD(pic_register_sources, atpic_register_sources),
@@ -273,7 +277,7 @@ atpic_enable_source(device_t pic, struct intsrc *isrc)
273277
}
274278

275279
static void
276-
atpic_disable_intr(device_t pic, struct intsrc *isrc)
280+
atpic_disable_intr(device_t pic, struct intsrc *isrc, enum eoi_flag eoi)
277281
{
278282
struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
279283
struct atpic *ap = device_get_softc(isrc->is_event.ie_pic);
@@ -289,18 +293,27 @@ atpic_disable_intr(device_t pic, struct intsrc *isrc)
289293
* a function pointer. All of the referenced variables should
290294
* still be hot in the cache.
291295
*/
292-
if (isrc->is_event.ie_pic == atpics[MASTER].at_pic)
293-
_atpic_eoi_master(isrc);
294-
else
295-
_atpic_eoi_slave(isrc);
296+
if (eoi == PIC_EOI) {
297+
if (isrc->is_event.ie_pic == atpics[MASTER].at_pic)
298+
_atpic_eoi_master(isrc);
299+
else
300+
_atpic_eoi_slave(isrc);
301+
}
296302

297303
spinlock_exit();
298304
}
299305

306+
static void
307+
atpic_disable_source(device_t pic, struct intsrc *isrc)
308+
{
309+
310+
atpic_disable_intr(pic, isrc, PIC_EOI);
311+
}
312+
300313
static void
301314
atpic_eoi(device_t pic, struct intsrc *isrc)
302315
{
303-
/* Reference the above comment (atpic_disable_intr()) */
316+
/* Reference the above comment (atpic_disable_source()) */
304317
if (isrc->is_event.ie_pic == atpics[MASTER].at_pic) {
305318
#ifndef AUTO_EOI_1
306319
spinlock_enter();

sys/x86/isa/clock.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,11 @@ int i8254_max_count;
8888
static int i8254_timecounter = 1;
8989

9090
static struct mtx clock_lock;
91+
static struct intsrc *i8254_intsrc;
9192
static uint16_t i8254_lastcount;
9293
static uint16_t i8254_offset;
94+
static pic_source_pending_t *i8254_pending;
9395
static int i8254_ticked;
94-
static struct intsrc *i8254_intsrc;
9596

9697
struct attimer_softc {
9798
int intr_en;
@@ -492,8 +493,8 @@ i8254_get_timecount(struct timecounter *tc)
492493
(!i8254_ticked && (clkintr_pending ||
493494
((count < 20 || (!(flags & PSL_I) &&
494495
count < i8254_max_count / 2u)) &&
495-
i8254_intsrc != NULL &&
496-
PIC_SOURCE_PENDING(i8254_intsrc->is_event.ie_pic, i8254_intsrc))))) {
496+
i8254_pending != NULL &&
497+
i8254_pending(i8254_intsrc->is_event.ie_pic, i8254_intsrc))))) {
497498
i8254_ticked = 1;
498499
i8254_offset += i8254_max_count;
499500
}
@@ -572,6 +573,8 @@ attimer_attach(device_t dev)
572573
&sc->port_rid, IO_TIMER1, IO_TIMER1 + 3, 4, RF_ACTIVE)))
573574
device_printf(dev,"Warning: Couldn't map I/O.\n");
574575
i8254_intsrc = intr_lookup_source(0);
576+
if (i8254_intsrc != NULL)
577+
i8254_pending = KOBJOPLOOKUP((kobj_t)(i8254_intsrc->is_event.ie_pic), pic_source_pending);
575578
resource_int_value(device_get_name(dev), device_get_unit(dev),
576579
"timecounter", &i8254_timecounter);
577580
set_i8254_freq(MODE_STOP, 0);

sys/x86/x86/intr_machdep.c

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,7 @@ static struct timeout_task intrbalance_task;
8888
static struct sx intrsrc_lock;
8989
static struct mtx intrpic_lock;
9090
static struct mtx intrcnt_lock;
91-
struct pic_entr {
92-
TAILQ_ENTRY(pic_entr) pics;
93-
x86pic_t pic;
94-
};
95-
static TAILQ_HEAD(pics_head, pic_entr) pics = TAILQ_HEAD_INITIALIZER(pics);
91+
static pic_base_softc_t pics = { NULL, NULL };
9692
u_int num_io_irqs;
9793

9894
#if defined(SMP) && !defined(EARLY_AP_STARTUP)
@@ -123,7 +119,7 @@ static void intrcnt_register(struct intsrc *is);
123119
/*
124120
* SYSINIT levels for SI_SUB_INTR:
125121
*
126-
* SI_ORDER_FIRST: Initialize locks and pics TAILQ, xen_hvm_cpu_init
122+
* SI_ORDER_FIRST: Initialize locks and pics list, xen_hvm_cpu_init
127123
* SI_ORDER_SECOND: Xen PICs
128124
* SI_ORDER_THIRD: Add I/O APIC PICs, alloc MSI and Xen IRQ ranges
129125
* SI_ORDER_FOURTH: Add 8259A PICs
@@ -135,11 +131,13 @@ static void intrcnt_register(struct intsrc *is);
135131
static int
136132
intr_pic_registered(device_t pic)
137133
{
138-
struct pic_entr *p;
134+
device_t p = pics.next;
139135

140-
TAILQ_FOREACH(p, &pics, pics) {
141-
if (p->pic == pic)
136+
/* TAILQ_FOREACH(p, &pics, pics) { */
137+
while (p) {
138+
if (p == pic)
142139
return (1);
140+
p = ((pic_base_softc_t *)device_get_softc(p))->next;
143141
}
144142
return (0);
145143
}
@@ -176,9 +174,6 @@ intr_create_pic(const char *name, u_int unit, driver_t *driver)
176174
void
177175
intr_register_pic(device_t pic)
178176
{
179-
struct pic_entr *entr = malloc(sizeof(*entr), M_INTR, M_WAITOK);
180-
181-
entr->pic = pic;
182177

183178
mtx_lock(&intrpic_lock);
184179
if (__predict_false(intr_pic_registered(pic)))
@@ -189,8 +184,17 @@ intr_register_pic(device_t pic)
189184
#endif
190185
("ERROR: %s: called with already registered PIC",
191186
__func__);
192-
else
193-
TAILQ_INSERT_TAIL(&pics, entr, pics);
187+
else {
188+
device_t p = pics.prev;
189+
pic_base_softc_t *softc = device_get_softc(pic);
190+
softc->next = NULL;
191+
softc->prev = p;
192+
if (p != NULL)
193+
((pic_base_softc_t *)device_get_softc(p))->next = pic;
194+
else
195+
pics.next = pic;
196+
pics.prev = pic;
197+
}
194198
mtx_unlock(&intrpic_lock);
195199
}
196200

@@ -201,7 +205,7 @@ intr_register_pic(device_t pic)
201205
static void
202206
intr_init_sources(void *arg)
203207
{
204-
struct pic_entr *pic;
208+
device_t pic = pics.next;
205209

206210
MPASS(num_io_irqs > 0);
207211

@@ -240,8 +244,10 @@ intr_init_sources(void *arg)
240244
* single-threaded at this point in startup so the list of
241245
* PICs shouldn't change.
242246
*/
243-
TAILQ_FOREACH(pic, &pics, pics)
244-
PIC_REGISTER_SOURCES(pic->pic);
247+
while (pic) {
248+
PIC_REGISTER_SOURCES(pic);
249+
pic = ((pic_base_softc_t *)device_get_softc(pic))->next;
250+
}
245251
}
246252
SYSINIT(intr_init_sources, SI_SUB_INTR, SI_ORDER_FOURTH + 1, intr_init_sources,
247253
NULL);
@@ -290,7 +296,7 @@ intr_disable_all(void)
290296
is = interrupt_sources[v];
291297
if (is == NULL)
292298
continue;
293-
PIC_DISABLE_INTR(is->is_event.ie_pic, is);
299+
PIC_DISABLE_INTR(is->is_event.ie_pic, is, PIC_EOI);
294300
}
295301
}
296302

@@ -338,7 +344,8 @@ intr_remove_handler(struct intsrc *isrc, struct intr_handler *handler)
338344
sx_xlock(&intrsrc_lock);
339345
isrc->is_handlers--;
340346
if (isrc->is_handlers == 0)
341-
PIC_DISABLE_INTR(isrc->is_event.ie_pic, isrc);
347+
PIC_DISABLE_INTR(isrc->is_event.ie_pic, isrc,
348+
PIC_NO_EOI);
342349
intrcnt_updatename(isrc);
343350
sx_xunlock(&intrsrc_lock);
344351
}
@@ -422,25 +429,29 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
422429
void
423430
intr_resume(bool suspend_cancelled)
424431
{
425-
struct pic_entr *pic;
432+
device_t pic = pics.next;
426433

427434
#ifndef DEV_ATPIC
428435
atpic_reset();
429436
#endif
430437
mtx_lock(&intrpic_lock);
431-
TAILQ_FOREACH(pic, &pics, pics)
432-
PIC_RESUME(pic->pic, suspend_cancelled);
438+
while (pic) {
439+
PIC_RESUME(pic, suspend_cancelled);
440+
pic = ((pic_base_softc_t *)device_get_softc(pic))->next;
441+
}
433442
mtx_unlock(&intrpic_lock);
434443
}
435444

436445
void
437446
intr_suspend(void)
438447
{
439-
struct pic_entr *pic;
448+
device_t pic = pics.prev;
440449

441450
mtx_lock(&intrpic_lock);
442-
TAILQ_FOREACH_REVERSE(pic, &pics, pics_head, pics)
443-
PIC_SUSPEND(pic->pic);
451+
while (pic) {
452+
PIC_SUSPEND(pic);
453+
pic = ((pic_base_softc_t *)device_get_softc(pic))->prev;
454+
}
444455
mtx_unlock(&intrpic_lock);
445456
}
446457

@@ -487,7 +498,8 @@ static device_method_t pic_base_methods[] = {
487498
DEVMETHOD_END
488499
};
489500

490-
PUBLIC_DEFINE_CLASSN(pic_base, pic_base_class, pic_base_methods, 0);
501+
PUBLIC_DEFINE_CLASSN(pic_base, pic_base_class, pic_base_methods,
502+
sizeof(pic_base_softc_t));
491503

492504
static void
493505
intrcnt_setname(const char *name, int index)

sys/x86/x86/io_apic.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct ioapic_intsrc {
9494
};
9595

9696
struct ioapic {
97+
pic_base_softc_t pic_base_softc;
9798
u_int io_apic_id:8; /* Id as enumerated by MADT */
9899
u_int io_hw_apic_id:8; /* Content of APIC ID register */
99100
u_int io_intbase:8; /* System Interrupt base */
@@ -105,8 +106,10 @@ struct ioapic {
105106
device_t pci_dev; /* matched pci device, if found */
106107
struct resource *pci_wnd; /* BAR 0, should be same or alias to
107108
io_paddr */
108-
struct ioapic_intsrc io_pins[0];
109+
struct ioapic_intsrc io_pins[];
109110
};
111+
_Static_assert(offsetof(struct ioapic, pic_base_softc) == 0,
112+
".pic_base_softc misaligned from struct ioapic!");
110113

111114
static u_int ioapic_read(volatile ioapic_t *apic, int reg);
112115
static void ioapic_write(volatile ioapic_t *apic, int reg, u_int val);
@@ -514,12 +517,25 @@ ioapic_enable_intr(device_t pic, struct intsrc *isrc)
514517
}
515518

516519
static void
517-
ioapic_disable_intr(x86pic_t pic, struct intsrc *isrc)
520+
ioapic_disable_intr(device_t pic, struct intsrc *isrc, enum eoi_flag eoi)
518521
{
519522
struct ioapic_intsrc *intpin = (struct ioapic_intsrc *)isrc;
523+
struct ioapic *io = device_get_softc(isrc->is_event.ie_pic);
524+
uint32_t flags;
520525
u_int vector;
521526

522-
ioapic_disable_source(pic, isrc);
527+
mtx_lock_spin(&icu_lock);
528+
if (!intpin->io_masked && !intpin->io_edgetrigger) {
529+
flags = intpin->io_lowreg | IOART_INTMSET;
530+
ioapic_write(io->io_addr,
531+
IOAPIC_REDTBL_LO(intpin->io_intpin), flags);
532+
intpin->io_masked = 1;
533+
}
534+
535+
if (eoi == PIC_EOI)
536+
_ioapic_eoi_source(io, intpin);
537+
538+
mtx_unlock_spin(&icu_lock);
523539

524540
if (intpin->io_vector != 0) {
525541
/* Mask this interrupt pin and free its APIC vector. */

sys/x86/x86/local_apic.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ static const device_method_t lapic_methods[] = {
474474
DEVMETHOD_END
475475
};
476476

477-
PRIVATE_DEFINE_CLASSN(lapic, lapic_class, lapic_methods, 0, pic_base_class);
477+
PRIVATE_DEFINE_CLASSN(lapic, lapic_class, lapic_methods,
478+
sizeof(pic_base_softc_t), pic_base_class);
478479

479480
static uint32_t
480481
lvt_mode_impl(struct lapic *la, struct lvt *lvt, u_int pin, uint32_t value)

sys/x86/x86/msi.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ static const device_method_t msi_methods[] = {
150150
DEVMETHOD_END
151151
};
152152

153-
PRIVATE_DEFINE_CLASSN(msi, msi_class, msi_methods, 0, pic_base_class);
153+
PRIVATE_DEFINE_CLASSN(msi, msi_class, msi_methods, sizeof(pic_base_softc_t),
154+
pic_base_class);
154155

155156
static device_t msi_pic;
156157

@@ -208,7 +209,7 @@ msi_enable_intr(device_t pic, struct intsrc *isrc)
208209
}
209210

210211
static void
211-
msi_disable_intr(device_t pic, struct intsrc *isrc)
212+
msi_disable_intr(device_t pic, struct intsrc *isrc, enum eoi_flag eoi)
212213
{
213214
struct msi_intsrc *msi = (struct msi_intsrc *)isrc;
214215

@@ -221,7 +222,8 @@ msi_disable_intr(device_t pic, struct intsrc *isrc)
221222
if (msi == NULL)
222223
return;
223224

224-
lapic_eoi();
225+
if (eoi == PIC_EOI)
226+
lapic_eoi();
225227

226228
msi->msi_enabled--;
227229
if (msi->msi_enabled == 0) {

sys/x86/x86/pic_if.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
#include <machine/interrupt.h>
3030

3131
#include "intr_event_if.h"
32+
33+
/* Flags for pic_disable_intr() */
34+
enum eoi_flag {
35+
PIC_EOI,
36+
PIC_NO_EOI,
37+
};
3238
};
3339

3440
CODE {
@@ -73,6 +79,7 @@
7379
METHOD void disable_intr {
7480
device_t pic;
7581
struct intsrc *isrc;
82+
enum eoi_flag eoi;
7683
};
7784

7885
METHOD int source_pending {

0 commit comments

Comments
 (0)