938
964
u8DeliveryMode, iVector, u8Polarity, u8TriggerMode);
968
* Local interrupt delivery, for devices attached to the CPU's LINT0/LINT1 pin.
969
* Normally used for 8259A PIC and NMI.
971
PDMBOTHCBDECL(int) apicLocalInterrupt(PPDMDEVINS pDevIns, uint8_t u8Pin, uint8_t u8Level)
973
APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
974
APICState *s = getLapicById(dev, 0);
976
Assert(PDMCritSectIsOwner(dev->CTX_SUFF(pCritSect)));
977
LogFlow(("apicLocalInterrupt: pDevIns=%p u8Pin=%x\n", pDevIns, u8Pin));
979
/* If LAPIC is disabled, go straight to the CPU. */
980
if (!(s->spurious_vec & APIC_SV_ENABLE))
982
LogFlow(("apicLocalInterrupt: LAPIC disabled, delivering directly to CPU core.\n"));
984
cpuSetInterrupt(dev, s, PDMAPICIRQ_EXTINT);
986
cpuClearInterrupt(dev, s, PDMAPICIRQ_EXTINT);
991
/* If LAPIC is enabled, interrupts are subject to LVT programming. */
993
/* There are only two local interrupt pins. */
994
AssertMsgReturn(u8Pin <= 1, ("Invalid LAPIC pin %d\n", u8Pin), VERR_INVALID_PARAMETER);
996
/* NB: We currently only deliver local interrupts to the first CPU. In theory they
997
* should be delivered to all CPUs and it is the guest's responsibility to ensure
998
* no more than one CPU has the interrupt unmasked.
1002
u32Lvec = s->lvt[APIC_LVT_LINT0 + u8Pin]; /* Fetch corresponding LVT entry. */
1003
/* Drop int if entry is masked. May not be correct for level-triggered interrupts. */
1004
if (!(u32Lvec & APIC_LVT_MASKED))
1005
{ uint8_t u8Delivery;
1008
u8Delivery = (u32Lvec >> 8) & 7;
1011
case APIC_DM_EXTINT:
1012
Assert(u8Pin == 0); /* PIC should be wired to LINT0. */
1013
enmType = PDMAPICIRQ_EXTINT;
1014
/* ExtINT can be both set and cleared, NMI/SMI/INIT can only be set. */
1015
LogFlow(("apicLocalInterrupt: %s ExtINT interrupt\n", u8Level ? "setting" : "clearing"));
1017
cpuSetInterrupt(dev, s, enmType);
1019
cpuClearInterrupt(dev, s, enmType);
1020
return VINF_SUCCESS;
1022
/* External NMI should be wired to LINT1, but Linux sometimes programs
1023
* LVT0 to NMI delivery mode as well.
1025
enmType = PDMAPICIRQ_NMI;
1026
/* Currently delivering NMIs through here causes problems with NMI watchdogs
1027
* on certain Linux kernels, e.g. 64-bit CentOS 5.3. Disable NMIs for now.
1029
return VINF_SUCCESS;
1031
enmType = PDMAPICIRQ_SMI;
1035
/** @todo implement APIC_DM_FIXED! */
1036
static unsigned s_c = 0;
1038
LogRel(("delivery type APIC_DM_FIXED not implemented. u8Pin=%d u8Level=%d", u8Pin, u8Level));
1039
return VINF_SUCCESS;
1042
/** @todo implement APIC_DM_INIT? */
1045
static unsigned s_c = 0;
1047
AssertLogRelMsgFailed(("delivery type %d not implemented. u8Pin=%d u8Level=%d", u8Delivery, u8Pin, u8Level));
1048
return VERR_INTERNAL_ERROR_4;
1051
LogFlow(("apicLocalInterrupt: setting local interrupt type %d\n", enmType));
1052
cpuSetInterrupt(dev, s, enmType);
1054
return VINF_SUCCESS;
941
1057
#endif /* VBOX */
943
1059
/* return -1 if no bit is set */
2341
2462
#ifdef IN_RING3
2464
/* Print a 8-dword LAPIC bit map (256 bits). */
2465
static void lapicDumpVec(APICDeviceInfo *dev, APICState *lapic, PCDBGFINFOHLP pHlp, unsigned start)
2470
for (i = 0; i < 8; ++i)
2472
val = apic_mem_readl(dev, lapic, start + (i << 4));
2473
pHlp->pfnPrintf(pHlp, "%08X", val);
2475
pHlp->pfnPrintf(pHlp, "\n");
2478
/* Print basic LAPIC state. */
2479
static DECLCALLBACK(void) lapicInfoBasic(APICDeviceInfo *dev, APICState *lapic, PCDBGFINFOHLP pHlp)
2484
pHlp->pfnPrintf(pHlp, "Local APIC at %08X:\n", lapic->apicbase);
2485
val = apic_mem_readl(dev, lapic, 0x20);
2486
pHlp->pfnPrintf(pHlp, " LAPIC ID : %08X\n", val);
2487
pHlp->pfnPrintf(pHlp, " APIC ID = %02X\n", (val >> 24) & 0xff);
2488
val = apic_mem_readl(dev, lapic, 0x30);
2489
max_lvt = (val >> 16) & 0xff;
2490
pHlp->pfnPrintf(pHlp, " APIC VER : %08X\n", val);
2491
pHlp->pfnPrintf(pHlp, " version = %02X\n", val & 0xff);
2492
pHlp->pfnPrintf(pHlp, " lvts = %d\n", ((val >> 16) & 0xff) + 1);
2493
val = apic_mem_readl(dev, lapic, 0x80);
2494
pHlp->pfnPrintf(pHlp, " TPR : %08X\n", val);
2495
pHlp->pfnPrintf(pHlp, " task pri = %d/%d\n", (val >> 4) & 0xf, val & 0xf);
2496
val = apic_mem_readl(dev, lapic, 0xA0);
2497
pHlp->pfnPrintf(pHlp, " PPR : %08X\n", val);
2498
pHlp->pfnPrintf(pHlp, " cpu pri = %d/%d\n", (val >> 4) & 0xf, val & 0xf);
2499
val = apic_mem_readl(dev, lapic, 0xD0);
2500
pHlp->pfnPrintf(pHlp, " LDR : %08X\n", val);
2501
pHlp->pfnPrintf(pHlp, " log id = %02X\n", (val >> 24) & 0xff);
2502
val = apic_mem_readl(dev, lapic, 0xE0);
2503
pHlp->pfnPrintf(pHlp, " DFR : %08X\n", val);
2504
val = apic_mem_readl(dev, lapic, 0xF0);
2505
pHlp->pfnPrintf(pHlp, " SVR : %08X\n", val);
2506
pHlp->pfnPrintf(pHlp, " focus = %s\n", val & (1 << 9) ? "check off" : "check on");
2507
pHlp->pfnPrintf(pHlp, " lapic = %s\n", val & (1 << 8) ? "ENABLED" : "DISABLED");
2508
pHlp->pfnPrintf(pHlp, " vector = %02X\n", val & 0xff);
2509
pHlp->pfnPrintf(pHlp, " ISR : ");
2510
lapicDumpVec(dev, lapic, pHlp, 0x100);
2511
val = get_highest_priority_int(lapic->isr);
2512
pHlp->pfnPrintf(pHlp, " highest = %02X\n", val == ~0U ? 0 : val);
2513
pHlp->pfnPrintf(pHlp, " IRR : ");
2514
lapicDumpVec(dev, lapic, pHlp, 0x200);
2515
val = get_highest_priority_int(lapic->irr);
2516
pHlp->pfnPrintf(pHlp, " highest = %02X\n", val == ~0U ? 0 : val);
2517
val = apic_mem_readl(dev, lapic, 0x320);
2520
/* Print the more interesting LAPIC LVT entries. */
2521
static DECLCALLBACK(void) lapicInfoLVT(APICDeviceInfo *dev, APICState *lapic, PCDBGFINFOHLP pHlp)
2524
static const char *dmodes[] = { "Fixed ", "Reserved", "SMI", "Reserved",
2525
"NMI", "INIT", "Reserved", "ExtINT" };
2527
val = apic_mem_readl(dev, lapic, 0x320);
2528
pHlp->pfnPrintf(pHlp, " LVT Timer : %08X\n", val);
2529
pHlp->pfnPrintf(pHlp, " mode = %s\n", val & (1 << 17) ? "periodic" : "one-shot");
2530
pHlp->pfnPrintf(pHlp, " mask = %d\n", (val >> 16) & 1);
2531
pHlp->pfnPrintf(pHlp, " status = %s\n", val & (1 << 12) ? "pending" : "idle");
2532
pHlp->pfnPrintf(pHlp, " vector = %02X\n", val & 0xff);
2533
val = apic_mem_readl(dev, lapic, 0x350);
2534
pHlp->pfnPrintf(pHlp, " LVT LINT0 : %08X\n", val);
2535
pHlp->pfnPrintf(pHlp, " mask = %d\n", (val >> 16) & 1);
2536
pHlp->pfnPrintf(pHlp, " trigger = %s\n", val & (1 << 15) ? "level" : "edge");
2537
pHlp->pfnPrintf(pHlp, " rem irr = %d\n", (val >> 14) & 1);
2538
pHlp->pfnPrintf(pHlp, " polarty = %d\n", (val >> 13) & 1);
2539
pHlp->pfnPrintf(pHlp, " status = %s\n", val & (1 << 12) ? "pending" : "idle");
2540
pHlp->pfnPrintf(pHlp, " delivry = %s\n", dmodes[(val >> 8) & 7]);
2541
pHlp->pfnPrintf(pHlp, " vector = %02X\n", val & 0xff);
2542
val = apic_mem_readl(dev, lapic, 0x360);
2543
pHlp->pfnPrintf(pHlp, " LVT LINT1 : %08X\n", val);
2544
pHlp->pfnPrintf(pHlp, " mask = %d\n", (val >> 16) & 1);
2545
pHlp->pfnPrintf(pHlp, " trigger = %s\n", val & (1 << 15) ? "level" : "edge");
2546
pHlp->pfnPrintf(pHlp, " rem irr = %d\n", (val >> 14) & 1);
2547
pHlp->pfnPrintf(pHlp, " polarty = %d\n", (val >> 13) & 1);
2548
pHlp->pfnPrintf(pHlp, " status = %s\n", val & (1 << 12) ? "pending" : "idle");
2549
pHlp->pfnPrintf(pHlp, " delivry = %s\n", dmodes[(val >> 8) & 7]);
2550
pHlp->pfnPrintf(pHlp, " vector = %02X\n", val & 0xff);
2553
/* Print LAPIC timer state. */
2554
static DECLCALLBACK(void) lapicInfoTimer(APICDeviceInfo *dev, APICState *lapic, PCDBGFINFOHLP pHlp)
2559
pHlp->pfnPrintf(pHlp, "Local APIC timer:\n");
2560
val = apic_mem_readl(dev, lapic, 0x380);
2561
pHlp->pfnPrintf(pHlp, " Initial count : %08X\n", val);
2562
val = apic_mem_readl(dev, lapic, 0x390);
2563
pHlp->pfnPrintf(pHlp, " Current count : %08X\n", val);
2564
val = apic_mem_readl(dev, lapic, 0x3E0);
2565
pHlp->pfnPrintf(pHlp, " Divide config : %08X\n", val);
2566
divider = ((val >> 1) & 0x04) | (val & 0x03);
2567
pHlp->pfnPrintf(pHlp, " divider = %d\n", divider == 7 ? 1 : 2 << divider);
2571
* Info handler, device version. Dumps Local APIC(s) state according to given argument.
2573
* @param pDevIns Device instance which registered the info.
2574
* @param pHlp Callback functions for doing output.
2575
* @param pszArgs Argument string. Optional.
2577
static DECLCALLBACK(void) lapicInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
2579
APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
2582
lapic = getLapic(dev);
2584
if (pszArgs == NULL || !strcmp(pszArgs, "basic"))
2586
lapicInfoBasic(dev, lapic, pHlp);
2588
else if (!strcmp(pszArgs, "lvt"))
2590
lapicInfoLVT(dev, lapic, pHlp);
2592
else if (!strcmp(pszArgs, "timer"))
2594
lapicInfoTimer(dev, lapic, pHlp);
2598
pHlp->pfnPrintf(pHlp, "Invalid argument. Recognized arguments are 'basic', 'lvt', 'timer'.\n");
2603
* @copydoc FNSSMDEVLIVEEXEC
2605
static DECLCALLBACK(int) apicLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
2607
APICDeviceInfo *pThis = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
2609
SSMR3PutU32( pSSM, pThis->cCpus);
2610
SSMR3PutBool(pSSM, pThis->fIoApic);
2611
SSMR3PutU32( pSSM, pThis->enmVersion);
2612
AssertCompile(PDMAPICVERSION_APIC == 2);
2614
return VINF_SSM_DONT_CALL_AGAIN;
2344
2618
* @copydoc FNSSMDEVSAVEEXEC
2346
static DECLCALLBACK(int) apicSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
2620
static DECLCALLBACK(int) apicSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
2348
2622
APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
2625
apicLiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
2350
2627
/* save all APICs data, @todo: is it correct? */
2351
foreach_apic(dev, 0xffffffff, apic_save(pSSMHandle, apic));
2628
foreach_apic(dev, 0xffffffff, apic_save(pSSM, apic));
2353
2630
return VINF_SUCCESS;
2357
2634
* @copydoc FNSSMDEVLOADEXEC
2359
static DECLCALLBACK(int) apicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
2636
static DECLCALLBACK(int) apicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
2361
APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
2362
/* load all APICs data, @todo: is it correct? */
2363
foreach_apic(dev, 0xffffffff,
2364
if (apic_load(pSSMHandle, apic, u32Version))
2638
APICDeviceInfo *pThis = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
2640
if ( uVersion != APIC_SAVED_STATE_VERSION
2641
&& uVersion != APIC_SAVED_STATE_VERSION_VBOX_30
2642
&& uVersion != APIC_SAVED_STATE_VERSION_ANCIENT)
2643
return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
2646
if (uVersion > APIC_SAVED_STATE_VERSION_VBOX_30) {
2648
int rc = SSMR3GetU32(pSSM, &cCpus); AssertRCReturn(rc, rc);
2649
if (cCpus != pThis->cCpus)
2650
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - cCpus: saved=%#x config=%#x"), cCpus, pThis->cCpus);
2652
rc = SSMR3GetBool(pSSM, &fIoApic); AssertRCReturn(rc, rc);
2653
if (fIoApic != pThis->fIoApic)
2654
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - fIoApic: saved=%RTbool config=%RTbool"), fIoApic, pThis->fIoApic);
2655
uint32_t uApicVersion;
2656
rc = SSMR3GetU32(pSSM, &uApicVersion); AssertRCReturn(rc, rc);
2657
if (uApicVersion != (uint32_t)pThis->enmVersion)
2658
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - uApicVersion: saved=%#x config=%#x"), uApicVersion, pThis->enmVersion);
2661
if (uPass != SSM_PASS_FINAL)
2662
return VINF_SUCCESS;
2664
/* load all APICs data */ /** @todo: is it correct? */
2665
foreach_apic(pThis, 0xffffffff,
2666
if (apic_load(pSSM, apic, uVersion)) {
2366
2667
AssertFailed();
2367
2668
return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
2794
3108
#ifdef IN_RING3
3111
* Info handler, device version. Dumps I/O APIC state.
3113
* @param pDevIns Device instance which registered the info.
3114
* @param pHlp Callback functions for doing output.
3115
* @param pszArgs Argument string. Optional and specific to the handler.
3117
static DECLCALLBACK(void) ioapicInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
3119
IOAPICState *s = PDMINS_2_DATA(pDevIns, IOAPICState *);
3124
pHlp->pfnPrintf(pHlp, "I/O APIC at %08X:\n", 0xfec00000);
3125
val = s->id << 24; /* Would be nice to call ioapic_mem_readl() directly, but that's not so simple. */
3126
pHlp->pfnPrintf(pHlp, " IOAPICID : %08X\n", val);
3127
pHlp->pfnPrintf(pHlp, " APIC ID = %02X\n", (val >> 24) & 0xff);
3128
val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16);
3129
max_redir = (val >> 16) & 0xff;
3130
pHlp->pfnPrintf(pHlp, " IOAPICVER : %08X\n", val);
3131
pHlp->pfnPrintf(pHlp, " version = %02X\n", val & 0xff);
3132
pHlp->pfnPrintf(pHlp, " redirs = %d\n", ((val >> 16) & 0xff) + 1);
3134
pHlp->pfnPrintf(pHlp, " IOAPICARB : %08X\n", val);
3135
pHlp->pfnPrintf(pHlp, " arb ID = %02X\n", (val >> 24) & 0xff);
3136
Assert(sizeof(s->ioredtbl) / sizeof(s->ioredtbl[0]) > max_redir);
3137
pHlp->pfnPrintf(pHlp, "I/O redirection table\n");
3138
pHlp->pfnPrintf(pHlp, " idx dst_mode dst_addr mask trigger rirr polarity dlvr_st dlvr_mode vector\n");
3139
for (i = 0; i <= max_redir; ++i)
3141
static const char *dmodes[] = { "Fixed ", "LowPri", "SMI ", "Resrvd",
3142
"NMI ", "INIT ", "Resrvd", "ExtINT" };
3144
pHlp->pfnPrintf(pHlp, " %02d %s %02X %d %s %d %s %s %s %3d (%016llX)\n",
3146
s->ioredtbl[i] & (1 << 11) ? "log " : "phys", /* dest mode */
3147
(int)(s->ioredtbl[i] >> 56), /* dest addr */
3148
(int)(s->ioredtbl[i] >> 16) & 1, /* mask */
3149
s->ioredtbl[i] & (1 << 15) ? "level" : "edge ", /* trigger */
3150
(int)(s->ioredtbl[i] >> 14) & 1, /* remote IRR */
3151
s->ioredtbl[i] & (1 << 13) ? "activelo" : "activehi", /* polarity */
3152
s->ioredtbl[i] & (1 << 12) ? "pend" : "idle", /* delivery status */
3153
dmodes[(s->ioredtbl[i] >> 8) & 0x07], /* delivery mode */
3154
(int)s->ioredtbl[i] & 0xff, /* vector */
3155
s->ioredtbl[i] /* entire register */
2797
3161
* @copydoc FNSSMDEVSAVEEXEC
2799
static DECLCALLBACK(int) ioapicSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
3163
static DECLCALLBACK(int) ioapicSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
2801
3165
IOAPICState *s = PDMINS_2_DATA(pDevIns, IOAPICState *);
2802
ioapic_save(pSSMHandle, s);
3166
ioapic_save(pSSM, s);
2803
3167
return VINF_SUCCESS;
2807
3171
* @copydoc FNSSMDEVLOADEXEC
2809
static DECLCALLBACK(int) ioapicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
3173
static DECLCALLBACK(int) ioapicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
2811
3175
IOAPICState *s = PDMINS_2_DATA(pDevIns, IOAPICState *);
2813
if (ioapic_load(pSSMHandle, s, u32Version)) {
3177
if (ioapic_load(pSSM, s, uVersion)) {
2814
3178
AssertFailed();
2815
3179
return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
3181
Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
2818
3183
return VINF_SUCCESS;