Page 1 of 1

Send IPI won't cause an interrupt

Posted: Wed Jun 08, 2022 5:54 am
by nifanfa
Hi! and Here is my code. But no matter what vector i send to apic_id 1 it still won't get any interrupt. but the IDT is working. i can devide zero to get isr0
https://github.com/nifanfa/MOOS/blob/6c ... IC.cs#L109
https://github.com/nifanfa/MOOS/blob/6c ... SMP.cs#L42

Re: Send IPI won't cause an interrupt

Posted: Wed Jun 08, 2022 5:56 am
by nifanfa
apic_id 1 is core 1. and it is valid

Re: Send IPI won't cause an interrupt

Posted: Wed Jun 08, 2022 10:23 am
by Octocontrabass
I think you're a little confused about how hexadecimal works.

It looks like you're using QEMU. Have you tried using the "info registers" and "info lapic" commands in QEMU's monitor to check if the AP is configured correctly?

Re: Send IPI won't cause an interrupt

Posted: Wed Jun 08, 2022 11:16 am
by nifanfa
Octocontrabass wrote:I think you're a little confused about how hexadecimal works.

It looks like you're using QEMU. Have you tried using the "info registers" and "info lapic" commands in QEMU's monitor to check if the AP is configured correctly?
Hey Octocontrabass!
now it works fine on qemu. but it doesn't work on VMware or real hardware. it still confused me

Re: Send IPI won't cause an interrupt

Posted: Wed Jun 08, 2022 11:32 am
by nifanfa

Code: Select all

using MOOS.Misc;

namespace MOOS.Driver
{
    public static unsafe partial class LocalAPIC
    {
        private const int LAPIC_ID = 0x0020;
        private const int LAPIC_VER = 0x0030;
        private const int LAPIC_TPR = 0x0080;
        private const int LAPIC_APR = 0x0090;
        private const int LAPIC_PPR = 0x00a0;
        private const int LAPIC_EOI = 0x00b0;
        private const int LAPIC_RRD = 0x00c0;
        private const int LAPIC_LDR = 0x00d0;
        private const int LAPIC_DFR = 0x00e0;
        private const int LAPIC_SVR = 0x00f0;
        private const int LAPIC_ISR = 0x0100;
        private const int LAPIC_TMR = 0x0180;
        private const int LAPIC_IRR = 0x0200;
        private const int LAPIC_ESR = 0x0280;
        private const int LAPIC_ICRLO = 0x0300;
        private const int LAPIC_ICRHI = 0x0310;
        private const int LAPIC_TIMER = 0x0320;
        private const int LAPIC_THERMAL = 0x0330;
        private const int LAPIC_PERF = 0x0340;
        private const int LAPIC_LINT0 = 0x0350;
        private const int LAPIC_LINT1 = 0x0360;
        private const int LAPIC_ERROR = 0x0370;
        private const int LAPIC_TICR = 0x0380;
        private const int LAPIC_TCCR = 0x0390;
        private const int LAPIC_TDCR = 0x03e0;

        private const int ICR_FIXED = 0x00000000;
        private const int ICR_LOWEST = 0x00000100;
        private const int ICR_SMI = 0x00000200;
        private const int ICR_NMI = 0x00000400;
        private const int ICR_INIT = 0x00000500;
        private const int ICR_STARTUP = 0x00000600;

        private const int ICR_PHYSICAL = 0x00000000;
        private const int ICR_LOGICAL = 0x00000800;

        private const int ICR_IDLE = 0x00000000;
        private const int ICR_SEND_PENDING = 0x00001000;

        private const int ICR_DEASSERT = 0x00000000;
        private const int ICR_ASSERT = 0x00004000;

        private const int ICR_EDGE = 0x00000000;
        private const int ICR_LEVEL = 0x00008000;

        private const int ICR_NO_SHORTHAND = 0x00000000;
        private const int ICR_SELF = 0x00040000;
        private const int ICR_ALL_INCLUDING_SELF = 0x00080000;
        private const int ICR_ALL_EXCLUDING_SELF = 0x000c0000;

        private const int ICR_DESTINATION_SHIFT = 24;

        static uint In(uint reg)
        {
            return MMIO.In32((uint*)(ACPI.MADT->LocalAPICAddress + reg));
        }

        static void Out(uint reg, uint data)
        {
            MMIO.Out32((uint*)(ACPI.MADT->LocalAPICAddress + reg), data);
        }

        public static void EndOfInterrupt()
        {
            Out((uint)LAPIC_EOI, 0);
        }

        public static void Initialize()
        {
            //Enable All Interrupts
            Out((uint)LAPIC_TPR, 0);

            // Logical Destination Mode
            Out((uint)LAPIC_DFR, 0xffffffff);   // Flat mode
            Out((uint)LAPIC_LDR, 0 << 24);   // All cpus use logical id 0

            // Configure Spurious Interrupt Vector Register
            Out((uint)LAPIC_SVR, 0x100 | 0xff);

            if(SMP.ThisCPU == 0)
                Console.WriteLine("[Local APIC] Local APIC initialized");
        }

        public static uint GetId()
        {
            return In((uint)LAPIC_ID) >> 24;
        }

        public static void SendInit(uint apic_id)
        {
            Out((uint)LAPIC_ICRHI, apic_id << ICR_DESTINATION_SHIFT);
            Out((uint)LAPIC_ICRLO, (uint)(ICR_INIT | ICR_PHYSICAL
                | ICR_ASSERT | ICR_EDGE | ICR_NO_SHORTHAND));

            while ((In((uint)LAPIC_ICRLO) & ICR_SEND_PENDING) != 0) ;
        }


        public static void SendInterrupt(uint apic_id, uint vector)
        {
            Out((uint)LAPIC_ICRHI, apic_id << ICR_DESTINATION_SHIFT);
            Out((uint)LAPIC_ICRLO, vector | (uint)ICR_FIXED | (uint)ICR_NO_SHORTHAND);

            while ((In((uint)LAPIC_ICRLO) & ICR_SEND_PENDING) != 0) ;
        }

        public static void SendStartup(uint apic_id, uint vector)
        {
            Out((uint)LAPIC_ICRHI, apic_id << ICR_DESTINATION_SHIFT);
            Out((uint)LAPIC_ICRLO, vector | (uint)ICR_STARTUP
                | (uint)ICR_PHYSICAL | (uint)ICR_ASSERT | (uint)ICR_EDGE | (uint)ICR_NO_SHORTHAND);

            while ((In((uint)LAPIC_ICRLO) & ICR_SEND_PENDING) != 0) ;
        }
    }
}

Re: Send IPI won't cause an interrupt

Posted: Wed Jun 08, 2022 11:32 am
by nifanfa

Code: Select all

public static void ApplicationProcessorMain(int Core)
        {
            SSE.enable_sse();
            LocalAPIC.Initialize();
            //Console.WriteLine("Hello from Application Processor");
            for (; ; ) SMP.Take()();
        }

Re: Send IPI won't cause an interrupt

Posted: Wed Jun 08, 2022 11:27 pm
by nifanfa
Nvm. problem resolved.

It is because that SendIPI can't issue a exception interrupt