Hi,<br><br>I am trying to execute a c program to send the INIT-SIPI-SIPI sequence to <br>a core after making it go offline (echo 0 > /sys/devices/system/cpu/cpu3/online). But it seems <br>that the program is not working because when it reads back the apic register just after writing to it <br>
the value is not the same as what was written.Following is the code for the program. The apic id <br>of the core to be restarted is 5 as seen from cat /proc/cpuinfo. Please let me know if I am doing something wrong.<br><br>
Thanks<br>- Vaibhav Jain<br><b><u><br>Code :<br></u></b><br>typedef unsigned int u32;<br><br>#define MAP_LEN 0x1000 //4 KB page<br>#define BUFLEN 100<br>#define APIC_BASE 0xfee00000<br>#define APIC_ICR_low 0xfee00300<br>
#define APIC_ICR_high 0xfee00310<br>#define APIC_ICR_init 0x00004500<br>#define APIC_ICR_start 0x00004600<br>#define BOUNCE_CODE 0x1000<br><br>int apic_reset_cpu(cpu); <br><br>int main() <br>
{<br> int cpu;<br> <br> //make sure we have root permissions<br> if(iopl(3))<br> {<br> printf("Cannot get I/O permissions (being root helps)\n");<br> return -1;<br> }<br><br> cpu = 5;<br> <br>if ((apic_reset_cpu(cpu)) != 0)<br>
printf("INIT & Startup failed!\n");<br> <br> printf("INIT / SIPI sequence complete\n");<br> <br> return 0;<br>}<br><br><br>int apic_reset_cpu(int cpu)<br>{<br> unsigned long tmpaddress, apic_icr, *apic_phy_addr;<br>
int fd, sleep_now=0;<br><br> //open the main memory file<br> fd = open ( "/dev/mem", O_RDWR); <br><br> printf("Assuming APIC physical base: %lx \n", APIC_BASE);<br> tmpaddress = (unsigned long) mmap(NULL, MAP_LEN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off_t)APIC_BASE);<br>
<br> if(tmpaddress == (unsigned long)MAP_FAILED) //check if it worked<br> {<br> perror("Mapping memory for absolute memory access failed.\n");<br> return -3;<br> }<br> <br> //prep ICR high<br> apic_icr = tmpaddress;<br>
apic_icr +=0x310;<br> apic_phy_addr = (unsigned long *) apic_icr;<br> *apic_phy_addr = cpu << 24;<br> <br> //read the value back <br> printf("\nICR high = %lx\n",*apic_phy_addr);<br> <br> //prep ICR low Send INIT and wait<br>
apic_icr = tmpaddress;<br> apic_icr += 0x300;<br> apic_phy_addr = (unsigned long *) apic_icr;<br> *apic_phy_addr = APIC_ICR_init;<br> sleep_now = usleep( 10000 ); //sleep 10 ms<br><br> printf("\nINIT SENT\n");<br>
<br>//read the value back<br> printf("\nICR low = %lx\n",*apic_phy_addr);<br><br> //prep ICR high again*<br> apic_icr = tmpaddress;<br> apic_icr +=0x310;<br> apic_phy_addr = (unsigned long *) apic_icr;<br> *apic_phy_addr = cpu << 24;<br>
<br><br> //prep for SIPI<br> apic_icr = tmpaddress;<br> apic_icr += 0x300;<br> apic_phy_addr = (unsigned long *) apic_icr;<br> *apic_phy_addr = APIC_ICR_start | (BOUNCE_CODE >> 12);<br> sleep_now = usleep( 500 ); //sleep 500 usec <br>
<br> printf("\nSIPI SENT\n");<br> <br> //read the value back<br> printf("\nICR low = %lx\n",*apic_phy_addr);<br><br> *apic_phy_addr = APIC_ICR_start | (BOUNCE_CODE >> 12);<br><br> printf("\nSIPI SENT AGAIN\n");<br>
<br> //read the value back<br> printf("\nICR low = %lx\n",*apic_phy_addr);<br> printf("Unmapping APIC Base page\n");<br><br> tmpaddress &= 0xfffff000;<br> munmap(tmpaddress, MAP_LEN); <br> <br>
return 0;<br>}<br> <br>