{"id":1397,"date":"2012-03-04T21:54:48","date_gmt":"2012-03-04T03:54:48","guid":{"rendered":"http:\/\/peta.okechan.net\/blog\/?p=1397"},"modified":"2012-03-14T11:21:48","modified_gmt":"2012-03-14T02:21:48","slug":"xv6%e3%82%bd%e3%83%bc%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%89%e3%83%aa%e3%83%bc%e3%83%87%e3%82%a3%e3%83%b3%e3%82%b0-%e3%81%9d%e3%81%ae28","status":"publish","type":"post","link":"https:\/\/peta.okechan.net\/blog\/archives\/1397","title":{"rendered":"[xv6 #28] Chapter 2 &#8211; Traps, interrupts, and drivers &#8211; Code: Interrupts"},"content":{"rendered":"<p>\u30c6\u30ad\u30b9\u30c8\u306e37\u301c39\u30da\u30fc\u30b8<\/p>\n<h3>\u672c\u6587<\/h3>\n<p>\u30de\u30b6\u30fc\u30dc\u30fc\u30c9\u4e0a\u306e\u30c7\u30d0\u30a4\u30b9\u306f\u3001\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u3001xv6\u306f\u305d\u308c\u3089\u306e\u5272\u308a\u8fbc\u307f\u3092\u5236\u5fa1\u3059\u308b\u305f\u3081\u306b\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3002<br \/>\n\u30c7\u30d0\u30a4\u30b9\u306e\u30b5\u30dd\u30fc\u30c8\u7121\u3057\u3067\u306f\u3001xv6\u306f\u4f7f\u3044\u7269\u306b\u306a\u3089\u306a\u3044\u3060\u308d\u3046\u3002<br \/>\n\u30e6\u30fc\u30b6\u306f\u30ad\u30fc\u30dc\u30fc\u30c9\u3067\u30bf\u30a4\u30d7\u51fa\u6765\u306a\u3044\u3057\u3001\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306f\u30c7\u30a3\u30b9\u30af\u306b\u30c7\u30fc\u30bf\u3092\u4fdd\u7ba1\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u306a\u3044\u3057\u3001\u4ed6\u306b\u3082\u305f\u304f\u3055\u3093\u306e\u554f\u984c\u304c\u8d77\u304d\u308b\u3002<br \/>\n\u5e78\u3044\u306b\u3082\u3001\u5272\u308a\u8fbc\u307f\u3092\u8ffd\u52a0\u3057\u305f\u308a\u3001\u5358\u7d14\u306a\u30c7\u30d0\u30a4\u30b9\u3092\u30b5\u30dd\u30fc\u30c8\u3059\u308b\u4e8b\u306f\u3001\u96e3\u3057\u304f\u306a\u3044\u3002<br \/>\n\u4eca\u307e\u3067\u898b\u3066\u304d\u305f\u3088\u3046\u306b\u3001\u5272\u308a\u8fbc\u307f\u306f\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u3068\u4f8b\u5916\u306e\u305f\u3081\u306e\u30b3\u30fc\u30c9\u3068\u540c\u3058\u3082\u306e\u6d41\u7528\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<\/p>\n<p>\u5272\u308a\u8fbc\u307f\u306f\u3001\u3044\u3064\u3067\u3082\u30c7\u30d0\u30a4\u30b9\u306b\u751f\u6210\u3055\u308c\u5f97\u308b\u3068\u3044\u3046\u4e8b\u3092\u9664\u3044\u3066\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u306b\u4f3c\u3066\u3044\u308b\u3002<br \/>\n\u30de\u30b6\u30fc\u30dc\u30fc\u30c9\u4e0a\u306b\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306b\u6ce8\u610f\u304c\u5fc5\u8981\u306a\u3068\u304d\uff08\u4f8b\u3048\u3070\u30e6\u30fc\u30b6\u304c\u30ad\u30fc\u30dc\u30fc\u30c9\u306e\u6587\u5b57\u3092\u30bf\u30a4\u30d7\u3057\u305f\u3068\u304d\uff09\u306bCPU\u3078\u4fe1\u53f7\u3092\u9001\u308b\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u304c\u3042\u308b\u3002<br \/>\n\u6211\u3005\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306b\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3055\u305b\u3001CPU\u304c\u53d7\u3051\u53d6\u308b\u5272\u308a\u8fbc\u307f\u3092\u6574\u5099\u3059\u308b\u305f\u3081\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3002<\/p>\n<p>\u30bf\u30a4\u30de\u30fc\u30c7\u30d0\u30a4\u30b9\u3068\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u898b\u3066\u307f\u3088\u3046\u3002<br \/>\n\u6211\u3005\u306f\u3001\u30ab\u30fc\u30cd\u30eb\u304c\u6642\u9593\u306e\u7d4c\u904e\u3092\u8a8d\u8b58\u51fa\u6765\u308b\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u3001\u30ab\u30fc\u30cd\u30eb\u304c\u8907\u6570\u306e\u30d7\u30ed\u30bb\u30b9\u306e\u9593\u3067\u6642\u5206\u5272\u51fa\u6765\u308b\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u3001\u30bf\u30a4\u30de\u30fc\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u306b1\u79d2\u9593\u306b100\u56de\u306e\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3057\u3066\u6b32\u3057\u3044\u3002<br \/>\n1\u79d2\u9593\u306b100\u56de\u3068\u3044\u3046\u9078\u629e\u306f\u3001\u30d7\u30ed\u30bb\u30c3\u30b5\u304c\u5272\u308a\u8fbc\u307f\u306e\u5236\u5fa1\u306b\u5fd9\u6bba\u3055\u308c\u3066\u306a\u3044\u9593\u3001\u9069\u6b63\u306a\u5bfe\u8a71\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u53ef\u80fd\u306b\u3059\u308b\u3002<\/p>\n<p>x86\u30d7\u30ed\u30bb\u30c3\u30b5\u305d\u308c\u81ea\u8eab\u306e\u3088\u3046\u306b\u3001PC\u306e\u30de\u30b6\u30fc\u30dc\u30fc\u30c9\u306f\u9032\u5316\u3057\u3066\u304d\u305f\u3002<br \/>\n\u305d\u3057\u3066\u3001\u63d0\u4f9b\u3055\u308c\u308b\u5272\u308a\u8fbc\u307f\u306e\u65b9\u6cd5\u3082\u540c\u3058\u304f\u9032\u5316\u3057\u3066\u304d\u305f\u3002<br \/>\n\u521d\u671f\u306e\u30dc\u30fc\u30c9\u306f\u3001\u5358\u7d14\u306a\u30d7\u30ed\u30b0\u30e9\u30e0\u53ef\u80fd\u306a\u5272\u308a\u8fbc\u307f\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\uff08PIC\u3068\u547c\u3070\u308c\u308b\uff09\u3092\u6301\u3063\u3066\u3044\u305f\u3002<br \/>\n\u305d\u308c\u3092\u7ba1\u7406\u3059\u308b\u305f\u3081\u306e\u30b3\u30fc\u30c9\u3092picirq.c\u3067\u898b\u3064\u3051\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3060\u308d\u3046\u3002<\/p>\n<p>picirq.c\uff08\u4e00\u5fdc\u8f09\u305b\u3068\u304d\u307e\u3059\uff09<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Intel 8259A programmable interrupt controllers.\n\n#include &quot;types.h&quot;\n#include &quot;x86.h&quot;\n#include &quot;traps.h&quot;\n\n\/\/ I\/O Addresses of the two programmable interrupt controllers\n#define IO_PIC1         0x20    \/\/ Master (IRQs 0-7)\n#define IO_PIC2         0xA0    \/\/ Slave (IRQs 8-15)\n\n#define IRQ_SLAVE       2       \/\/ IRQ at which slave connects to master\n\n\/\/ Current IRQ mask.\n\/\/ Initial IRQ mask has interrupt 2 enabled (for slave 8259A).\nstatic ushort irqmask = 0xFFFF &amp; ~(1&lt;&lt;IRQ_SLAVE);\n\nstatic void\npicsetmask(ushort mask)\n{\n  irqmask = mask;\n  outb(IO_PIC1+1, mask);\n  outb(IO_PIC2+1, mask &gt;&gt; 8);\n}\n\nvoid\npicenable(int irq)\n{\n  picsetmask(irqmask &amp; ~(1&lt;&lt;irq));\n}\n\n\/\/ Initialize the 8259A interrupt controllers.\nvoid\npicinit(void)\n{\n  \/\/ mask all interrupts\n  outb(IO_PIC1+1, 0xFF);\n  outb(IO_PIC2+1, 0xFF);\n\n  \/\/ Set up master (8259A-1)\n\n  \/\/ ICW1:  0001g0hi\n  \/\/    g:  0 = edge triggering, 1 = level triggering\n  \/\/    h:  0 = cascaded PICs, 1 = master only\n  \/\/    i:  0 = no ICW4, 1 = ICW4 required\n  outb(IO_PIC1, 0x11);\n\n  \/\/ ICW2:  Vector offset\n  outb(IO_PIC1+1, T_IRQ0);\n\n  \/\/ ICW3:  (master PIC) bit mask of IR lines connected to slaves\n  \/\/        (slave PIC) 3-bit # of slave&#039;s connection to master\n  outb(IO_PIC1+1, 1&lt;&lt;IRQ_SLAVE);\n\n  \/\/ ICW4:  000nbmap\n  \/\/    n:  1 = special fully nested mode\n  \/\/    b:  1 = buffered mode\n  \/\/    m:  0 = slave PIC, 1 = master PIC\n  \/\/      (ignored when b is 0, as the master\/slave role\n  \/\/      can be hardwired).\n  \/\/    a:  1 = Automatic EOI mode\n  \/\/    p:  0 = MCS-80\/85 mode, 1 = intel x86 mode\n  outb(IO_PIC1+1, 0x3);\n\n  \/\/ Set up slave (8259A-2)\n  outb(IO_PIC2, 0x11);                  \/\/ ICW1\n  outb(IO_PIC2+1, T_IRQ0 + 8);      \/\/ ICW2\n  outb(IO_PIC2+1, IRQ_SLAVE);           \/\/ ICW3\n  \/\/ NB Automatic EOI mode doesn&#039;t tend to work on the slave.\n  \/\/ Linux source code says it&#039;s &quot;to be investigated&quot;.\n  outb(IO_PIC2+1, 0x3);                 \/\/ ICW4\n\n  \/\/ OCW3:  0ef01prs\n  \/\/   ef:  0x = NOP, 10 = clear specific mask, 11 = set specific mask\n  \/\/    p:  0 = no polling, 1 = polling mode\n  \/\/   rs:  0x = NOP, 10 = read IRR, 11 = read ISR\n  outb(IO_PIC1, 0x68);             \/\/ clear specific mask\n  outb(IO_PIC1, 0x0a);             \/\/ read IRR by default\n\n  outb(IO_PIC2, 0x68);             \/\/ OCW3\n  outb(IO_PIC2, 0x0a);             \/\/ OCW3\n\n  if(irqmask != 0xFFFF)\n    picsetmask(irqmask);\n}&amp;#91;\/sourcecode&amp;#93;\n\n\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30c3\u30b5PC\u30dc\u30fc\u30c9\u306e\u767b\u5834\u306b\u3088\u3063\u3066\u3001\u65b0\u3057\u3044\u5272\u308a\u8fbc\u307f\u306e\u5236\u5fa1\u65b9\u6cd5\u304c\u5fc5\u8981\u3068\u3055\u308c\u305f\u3002\n\u306a\u305c\u306a\u3089\u3001\u3069\u306eCPU\u3082\u5272\u308a\u8fbc\u307f\u3092\u5236\u5fa1\u3059\u308b\u305f\u3081\u306e\u5272\u308a\u8fbc\u307f\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u3092\u5fc5\u8981\u3068\u3057\u3001\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5bfe\u3059\u308b\u30eb\u30fc\u30c1\u30f3\u5272\u308a\u8fbc\u307f\u306e\u70ba\u306e\u624b\u6cd5\u304c\u5b58\u5728\u3059\u3079\u304d\u3060\u304b\u3089\u3067\u3042\u308b\u3002\n\u3053\u306e\u65b9\u6cd5\u306f\u30012\u3064\u306e\u90e8\u5206\u304b\u3089\u6210\u308b\u3002\n1\u3064\u306f\u3001I\/O\u30b7\u30b9\u30c6\u30e0\u90e8\u5206\uff08IO APIC, ioapic.c\uff09\u3001\u3082\u30461\u3064\u306f\u3001\u305d\u308c\u305e\u308c\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u30a2\u30bf\u30c3\u30c1\u3059\u308b\u90e8\u5206\uff08\u30ed\u30fc\u30ab\u30ebAPIC, lapic.c\uff09\u3067\u3042\u308b\u3002\nxv6\u306f\u3001\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30c3\u30b5\u7528\u306e\u30dc\u30fc\u30c9\u306e\u305f\u3081\u306b\u30c7\u30b6\u30a4\u30f3\u3055\u308c\u3001\u305d\u3057\u3066\u3069\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3082\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u53d6\u308b\u305f\u3081\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3055\u308c\u308b\u3002\n\nioapic.c\n&amp;#91;sourcecode language=&quot;c&quot;&amp;#93;\/\/ The I\/O APIC manages hardware interrupts for an SMP system.\n\/\/ http:\/\/www.intel.com\/design\/chipsets\/datashts\/29056601.pdf\n\/\/ See also picirq.c.\n\n#include &quot;types.h&quot;\n#include &quot;defs.h&quot;\n#include &quot;traps.h&quot;\n\n#define IOAPIC  0xFEC00000   \/\/ Default physical address of IO APIC\n\n#define REG_ID     0x00  \/\/ Register index: ID\n#define REG_VER    0x01  \/\/ Register index: version\n#define REG_TABLE  0x10  \/\/ Redirection table base\n\n\/\/ The redirection table starts at REG_TABLE and uses\n\/\/ two registers to configure each interrupt.  \n\/\/ The first (low) register in a pair contains configuration bits.\n\/\/ The second (high) register contains a bitmask telling which\n\/\/ CPUs can serve that interrupt.\n#define INT_DISABLED   0x00010000  \/\/ Interrupt disabled\n#define INT_LEVEL      0x00008000  \/\/ Level-triggered (vs edge-)\n#define INT_ACTIVELOW  0x00002000  \/\/ Active low (vs high)\n#define INT_LOGICAL    0x00000800  \/\/ Destination is CPU id (vs APIC ID)\n\nvolatile struct ioapic *ioapic;\n\n\/\/ IO APIC MMIO structure: write reg, then read or write data.\nstruct ioapic {\n  uint reg;\n  uint pad&amp;#91;3&amp;#93;;\n  uint data;\n};\n\nstatic uint\nioapicread(int reg)\n{\n  ioapic-&gt;reg = reg;\n  return ioapic-&gt;data;\n}\n\nstatic void\nioapicwrite(int reg, uint data)\n{\n  ioapic-&gt;reg = reg;\n  ioapic-&gt;data = data;\n}\n\nvoid\nioapicinit(void)\n{\n  int i, id, maxintr;\n\n  if(!ismp)\n    return;\n\n  ioapic = (volatile struct ioapic*)IOAPIC;\n  maxintr = (ioapicread(REG_VER) &gt;&gt; 16) &amp; 0xFF;\n  id = ioapicread(REG_ID) &gt;&gt; 24;\n  if(id != ioapicid)\n    cprintf(&quot;ioapicinit: id isn&#039;t equal to ioapicid; not a MP\\n&quot;);\n\n  \/\/ Mark all interrupts edge-triggered, active high, disabled,\n  \/\/ and not routed to any CPUs.\n  for(i = 0; i &lt;= maxintr; i++){\n    ioapicwrite(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i));\n    ioapicwrite(REG_TABLE+2*i+1, 0);\n  }\n}\n\nvoid\nioapicenable(int irq, int cpunum)\n{\n  if(!ismp)\n    return;\n\n  \/\/ Mark interrupt edge-triggered, active high,\n  \/\/ enabled, and routed to the given cpunum,\n  \/\/ which happens to be that cpu&#039;s APIC ID.\n  ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq);\n  ioapicwrite(REG_TABLE+2*irq+1, cpunum &lt;&lt; 24);\n}&amp;#91;\/sourcecode&amp;#93;\n\nlapic.c\n&amp;#91;sourcecode language=&quot;c&quot;&amp;#93;\/\/ The local APIC manages internal (non-I\/O) interrupts.\n\/\/ See Chapter 8 &amp; Appendix C of Intel processor manual volume 3.\n\n#include &quot;types.h&quot;\n#include &quot;defs.h&quot;\n#include &quot;memlayout.h&quot;\n#include &quot;traps.h&quot;\n#include &quot;mmu.h&quot;\n#include &quot;x86.h&quot;\n\n\/\/ Local APIC registers, divided by 4 for use as uint&amp;#91;&amp;#93; indices.\n#define ID      (0x0020\/4)   \/\/ ID\n#define VER     (0x0030\/4)   \/\/ Version\n#define TPR     (0x0080\/4)   \/\/ Task Priority\n#define EOI     (0x00B0\/4)   \/\/ EOI\n#define SVR     (0x00F0\/4)   \/\/ Spurious Interrupt Vector\n  #define ENABLE     0x00000100   \/\/ Unit Enable\n#define ESR     (0x0280\/4)   \/\/ Error Status\n#define ICRLO   (0x0300\/4)   \/\/ Interrupt Command\n  #define INIT       0x00000500   \/\/ INIT\/RESET\n  #define STARTUP    0x00000600   \/\/ Startup IPI\n  #define DELIVS     0x00001000   \/\/ Delivery status\n  #define ASSERT     0x00004000   \/\/ Assert interrupt (vs deassert)\n  #define DEASSERT   0x00000000\n  #define LEVEL      0x00008000   \/\/ Level triggered\n  #define BCAST      0x00080000   \/\/ Send to all APICs, including self.\n  #define BUSY       0x00001000\n  #define FIXED      0x00000000\n#define ICRHI   (0x0310\/4)   \/\/ Interrupt Command &amp;#91;63:32&amp;#93;\n#define TIMER   (0x0320\/4)   \/\/ Local Vector Table 0 (TIMER)\n  #define X1         0x0000000B   \/\/ divide counts by 1\n  #define PERIODIC   0x00020000   \/\/ Periodic\n#define PCINT   (0x0340\/4)   \/\/ Performance Counter LVT\n#define LINT0   (0x0350\/4)   \/\/ Local Vector Table 1 (LINT0)\n#define LINT1   (0x0360\/4)   \/\/ Local Vector Table 2 (LINT1)\n#define ERROR   (0x0370\/4)   \/\/ Local Vector Table 3 (ERROR)\n  #define MASKED     0x00010000   \/\/ Interrupt masked\n#define TICR    (0x0380\/4)   \/\/ Timer Initial Count\n#define TCCR    (0x0390\/4)   \/\/ Timer Current Count\n#define TDCR    (0x03E0\/4)   \/\/ Timer Divide Configuration\n\nvolatile uint *lapic;  \/\/ Initialized in mp.c\n\nstatic void\nlapicw(int index, int value)\n{\n  lapic&amp;#91;index&amp;#93; = value;\n  lapic&amp;#91;ID&amp;#93;;  \/\/ wait for write to finish, by reading\n}\n\/\/PAGEBREAK!\n\nvoid\nlapicinit(int c)\n{\n  if(!lapic) \n    return;\n\n  \/\/ Enable local APIC; set spurious interrupt vector.\n  lapicw(SVR, ENABLE | (T_IRQ0 + IRQ_SPURIOUS));\n\n  \/\/ The timer repeatedly counts down at bus frequency\n  \/\/ from lapic&amp;#91;TICR&amp;#93; and then issues an interrupt.  \n  \/\/ If xv6 cared more about precise timekeeping,\n  \/\/ TICR would be calibrated using an external time source.\n  lapicw(TDCR, X1);\n  lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));\n  lapicw(TICR, 10000000); \n\n  \/\/ Disable logical interrupt lines.\n  lapicw(LINT0, MASKED);\n  lapicw(LINT1, MASKED);\n\n  \/\/ Disable performance counter overflow interrupts\n  \/\/ on machines that provide that interrupt entry.\n  if(((lapic&amp;#91;VER&amp;#93;&gt;&gt;16) &amp; 0xFF) &gt;= 4)\n    lapicw(PCINT, MASKED);\n\n  \/\/ Map error interrupt to IRQ_ERROR.\n  lapicw(ERROR, T_IRQ0 + IRQ_ERROR);\n\n  \/\/ Clear error status register (requires back-to-back writes).\n  lapicw(ESR, 0);\n  lapicw(ESR, 0);\n\n  \/\/ Ack any outstanding interrupts.\n  lapicw(EOI, 0);\n\n  \/\/ Send an Init Level De-Assert to synchronise arbitration ID&#039;s.\n  lapicw(ICRHI, 0);\n  lapicw(ICRLO, BCAST | INIT | LEVEL);\n  while(lapic&#x5B;ICRLO] &amp; DELIVS)\n    ;\n\n  \/\/ Enable interrupts on the APIC (but not on the processor).\n  lapicw(TPR, 0);\n}\n\nint\ncpunum(void)\n{\n  \/\/ Cannot call cpu when interrupts are enabled:\n  \/\/ result not guaranteed to last long enough to be used!\n  \/\/ Would prefer to panic but even printing is chancy here:\n  \/\/ almost everything, including cprintf and panic, calls cpu,\n  \/\/ often indirectly through acquire and release.\n  if(readeflags()&amp;FL_IF){\n    static int n;\n    if(n++ == 0)\n      cprintf(&quot;cpu called from %x with interrupts enabled\\n&quot;,\n        __builtin_return_address(0));\n  }\n\n  if(lapic)\n    return lapic&#x5B;ID]&gt;&gt;24;\n  return 0;\n}\n\n\/\/ Acknowledge interrupt.\nvoid\nlapiceoi(void)\n{\n  if(lapic)\n    lapicw(EOI, 0);\n}\n\n\/\/ Spin for a given number of microseconds.\n\/\/ On real hardware would want to tune this dynamically.\nvoid\nmicrodelay(int us)\n{\n}\n\n#define IO_RTC  0x70\n\n\/\/ Start additional processor running entry code at addr.\n\/\/ See Appendix B of MultiProcessor Specification.\nvoid\nlapicstartap(uchar apicid, uint addr)\n{\n  int i;\n  ushort *wrv;\n  \n  \/\/ &quot;The BSP must initialize CMOS shutdown code to 0AH\n  \/\/ and the warm reset vector (DWORD based at 40:67) to point at\n  \/\/ the AP startup code prior to the &#x5B;universal startup algorithm].&quot;\n  outb(IO_RTC, 0xF);  \/\/ offset 0xF is shutdown code\n  outb(IO_RTC+1, 0x0A);\n  wrv = (ushort*)P2V((0x40&lt;&lt;4 | 0x67));  \/\/ Warm reset vector\n  wrv&amp;#91;0&amp;#93; = 0;\n  wrv&amp;#91;1&amp;#93; = addr &gt;&gt; 4;\n\n  \/\/ &quot;Universal startup algorithm.&quot;\n  \/\/ Send INIT (level-triggered) interrupt to reset other CPU.\n  lapicw(ICRHI, apicid&lt;&lt;24);\n  lapicw(ICRLO, INIT | LEVEL | ASSERT);\n  microdelay(200);\n  lapicw(ICRLO, INIT | LEVEL);\n  microdelay(100);    \/\/ should be 10ms, but too slow in Bochs!\n  \n  \/\/ Send startup IPI (twice!) to enter code.\n  \/\/ Regular hardware is supposed to only accept a STARTUP\n  \/\/ when it is in the halted state due to an INIT.  So the second\n  \/\/ should be ignored, but it is part of the official Intel algorithm.\n  \/\/ Bochs complains about the second one.  Too bad for Bochs.\n  for(i = 0; i &lt; 2; i++){\n    lapicw(ICRHI, apicid&lt;&lt;24);\n    lapicw(ICRLO, STARTUP | (addr&gt;&gt;12));\n    microdelay(200);\n  }\n}<\/pre>\n<p>\u30e6\u30cb\u30d7\u30ed\u30bb\u30c3\u30b5\u4e0a\u3067\u3082\u3061\u3083\u3093\u3068\u52d5\u304f\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u306b\u3001xv6\u306f\u3001\u30d7\u30ed\u30b0\u30e9\u30e0\u53ef\u80fd\u306a\u5272\u308a\u8fbc\u307f\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\uff08PIC\uff09\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002<br \/>\n\uff08picirq.c\u306epicinit\u95a2\u6570\uff09<br \/>\n\u3069\u306ePIC\u3082\u6700\u5927\u30678\u500b\u306e\u5272\u308a\u8fbc\u307f\uff08\u4f8b\u3048\u3070\u8907\u6570\u306e\u30c7\u30d0\u30a4\u30b9\uff09\u3092\u5236\u5fa1\u51fa\u6765\u3001\u305d\u3057\u3066\u305d\u308c\u3089\u3092\u30d7\u30ed\u30bb\u30c3\u30b5\u306e\u5272\u308a\u8fbc\u307f\u30d4\u30f3\u3078\u591a\u91cd\u9001\u4fe1\u3059\u308b\u3002<br \/>\n8\u500b\u4ee5\u4e0a\u306e\u30c7\u30d0\u30a4\u30b9\u306b\u5bfe\u5fdc\u3059\u308b\u305f\u3081\u3001\u8907\u6570\u306ePIC\u306f\u30ab\u30b9\u30b1\u30fc\u30c9\u63a5\u7d9a\u3055\u308c\u3001\u5178\u578b\u7684\u306a\u30dc\u30fc\u30c9\u306a\u3089\u6700\u4f4e\u3067\u30822\u3064\u306ePIC\u3092\u6301\u3064\u3002<br \/>\ninb\u547d\u4ee4\u3068outb\u547d\u4ee4\u3092\u4f7f\u3046\u3053\u3068\u3067\u3001xv6\u306f\u3001\u30de\u30b9\u30bf\u306bIRQ 0\u304b\u3089IRQ 7\u3092\u751f\u6210\u3055\u305b\u308b\u305f\u3081\u3001\u30b9\u30ec\u30fc\u30d6\u306bIRQ 8\u304b\u3089IRQ 15\uff08\u539f\u6587\u3067\u306f16\u306b\u306a\u3063\u3066\u308b\uff09\u3092\u751f\u6210\u3055\u305b\u308b\u305f\u3081\u306b\u3001\u305d\u308c\u3089\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002<br \/>\n\u6700\u521d\u306b\u3001xv6\u306fPIC\u306b\u5168\u3066\u306e\u5272\u308a\u8fbc\u307f\u3092\u30de\u30b9\u30af\u3055\u305b\u308b\u305f\u3081\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002<br \/>\ntimer.c\u306e\u30b3\u30fc\u30c9\u3067\u3001\u30bf\u30a4\u30de\u30fc\u30921\u306b\u30bb\u30c3\u30c8\u3057PIC\u4e0a\u306e\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3057\u3066\u3044\u308b\u3002<br \/>\n\uff08timer.c\u306etimerinit\u95a2\u6570\uff09<br \/>\n\u4eca\u306f\u3001PIC\u306e\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u306b\u95a2\u3057\u3066\u8a73\u7d30\u3092\u3044\u304f\u3064\u304b\u7701\u3044\u3066\u3044\u308b\u3002<br \/>\n\u305d\u308c\u3089\u306e\u8a73\u7d30\uff08PIC\u3001IOAPIC\u3001LAPIC\uff09\u306f\u3001\u3053\u306e\u30c6\u30ad\u30b9\u30c8\u3067\u306f\u91cd\u8981\u3067\u306f\u306a\u3044\u304c\u3001\u8208\u5473\u3092\u6301\u3063\u305f\u8aad\u8005\u306f\u305d\u308c\u3089\u306e\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3067\u53c2\u7167\u3055\u308c\u3066\u3044\u308b\u305d\u308c\u305e\u308c\u306e\u30c7\u30d0\u30a4\u30b9\u306e\u30de\u30cb\u30e5\u30a2\u30eb\u3092\u8abf\u3079\u308b\u4e8b\u304c\u3067\u304d\u308b\u3002<\/p>\n<p>timer.c<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Intel 8253\/8254\/82C54 Programmable Interval Timer (PIT).\n\/\/ Only used on uniprocessors;\n\/\/ SMP machines use the local APIC timer.\n\n#include \"types.h\"\n#include \"defs.h\"\n#include \"traps.h\"\n#include \"x86.h\"\n\n#define IO_TIMER1       0x040           \/\/ 8253 Timer #1\n\n\/\/ Frequency of all three count-down timers;\n\/\/ (TIMER_FREQ\/freq) is the appropriate count\n\/\/ to generate a frequency of freq Hz.\n\n#define TIMER_FREQ      1193182\n#define TIMER_DIV(x)    ((TIMER_FREQ+(x)\/2)\/(x))\n\n#define TIMER_MODE      (IO_TIMER1 + 3) \/\/ timer mode port\n#define TIMER_SEL0      0x00    \/\/ select counter 0\n#define TIMER_RATEGEN   0x04    \/\/ mode 2, rate generator\n#define TIMER_16BIT     0x30    \/\/ r\/w counter 16 bits, LSB first\n\nvoid\ntimerinit(void)\n{\n  \/\/ Interrupt 100 times\/sec.\n  outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);\n  outb(IO_TIMER1, TIMER_DIV(100) % 256);\n  outb(IO_TIMER1, TIMER_DIV(100) \/ 256);\n  picenable(IRQ_TIMER);\n}<\/pre>\n<p>\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30c3\u30b5\u306e\u5834\u5408\u3001xv6\u306f\u3001\u305d\u308c\u305e\u308c\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u4e0a\u3067IOAPIC\u3068LAPIC\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3002<br \/>\nIO APIC\u306f\u30c6\u30fc\u30d6\u30eb\u3092\u6301\u3061\u3001\u30d7\u30ed\u30bb\u30c3\u30b5\u306finb\u547d\u4ee4\u3084outb\u547d\u4ee4\u3092\u4f7f\u3046\u4ee3\u308f\u308a\u306b\u3001\u30e1\u30e2\u30ea\u30de\u30c3\u30d7\u30c9I\/O\u3092\u901a\u3057\u3066\u305d\u306e\u30c6\u30fc\u30d6\u30eb\u306e\u30a8\u30f3\u30c8\u30ea\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<br \/>\n\u521d\u671f\u5316\u4e2d\u3001xv6\u306f\u3001\u5272\u308a\u8fbc\u307f0\u3092IRQ 0\u306b\u5bfe\u5fdc\u4ed8\u3051\u308b\u3088\u3046\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002\uff081\u4ee5\u964d\u3082\u540c\u69d8\u306b\uff09<br \/>\n\u3057\u304b\u3057\u3001\u305d\u308c\u3089\u5168\u3066\u3092\u7121\u52b9\u5316\u3059\u308b\u3002<br \/>\n\u7279\u5b9a\u306e\u30c7\u30d0\u30a4\u30b9\u306f\u3001\u7279\u6709\u306e\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3057\u3001\u305d\u306e\u5272\u308a\u8fbc\u307f\u3092\u62c5\u5f53\u3059\u3079\u304d\u3067\u3042\u308b\u3068\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u4f1d\u3048\u308b\u3002<br \/>\n\u4f8b\u3048\u3070\u3001xv6\u306f\u30ad\u30fc\u30dc\u30fc\u30c9\u5272\u308a\u8fbc\u307f\u3092\u30d7\u30ed\u30bb\u30c3\u30b50\u306b\u9001\u308b\u3002<br \/>\n\uff08console.c\u306econsoleinit\u95a2\u6570\uff09<br \/>\n\u5f8c\u3067\u898b\u308b\u304c\u3001xv6\u306f\u30c7\u30a3\u30b9\u30af\u5272\u308a\u8fbc\u307f\u3092\u305d\u306e\u30b7\u30b9\u30c6\u30e0\u3067\u4e00\u756a\u756a\u53f7\u304c\u5927\u304d\u3044\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5272\u308a\u5f53\u3066\u308b\u3002<\/p>\n<p>console.c\u306econsoleinit\u95a2\u6570<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">void\nconsoleinit(void)\n{\n  initlock(&cons.lock, \"console\");\n  initlock(&input.lock, \"input\");\n\n  devsw&#x5B;CONSOLE].write = consolewrite;\n  devsw&#x5B;CONSOLE].read = consoleread;\n  cons.locking = 1;\n\n  picenable(IRQ_KBD);\n  ioapicenable(IRQ_KBD, 0);\n}<\/pre>\n<p>\u30bf\u30a4\u30de\u30fc\u30c1\u30c3\u30d7\u306fLAPIC\u306e\u4e2d\u306b\u3042\u308a\u3001\u305d\u306e\u304a\u304b\u3052\u3067\u3069\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3082\u500b\u5225\u306b\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u53d6\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<br \/>\nxv6\u306f\u3001\u305d\u308c\u3092lapic.c\u306elapicinit\u95a2\u6570\u3067\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3057\u3066\u3044\u308b\u3002<br \/>\n\u91cd\u8981\u306a\u884c\u306f\u3001\u30bf\u30a4\u30de\u30fc\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3057\u3066\u308b\u90e8\u5206\u3067\u3042\u308b\u3002<br \/>\n\uff08lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));\u306e\u90e8\u5206)<br \/>\n\u3053\u306e\u884c\u306f\u3001LAPIC\u306bIRQ_TIMER\u3067\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3055\u305b\u308b\u4e8b\u3092\u4f1d\u3048\u3066\u3044\u308b\u3002<br \/>\n\uff08traps.h\u306b#define IRQ_TIMER 0\u3068\u3042\u308aIRQ 0\u306b\u3042\u305f\u308b\uff09<br \/>\nlapicinit\u306e\u6700\u5f8c\u306e\u884c\uff08lapicw(TPR, 0);\uff09\u306f\u3001\u30ed\u30fc\u30ab\u30eb\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5272\u308a\u8fbc\u307f\u3092\u904b\u3076\u305f\u3081\u306bCPU\u306eLAPIC\u4e0a\u306e\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3059\u308b\u3002<\/p>\n<p>\u30d7\u30ed\u30bb\u30c3\u30b5\u306f\u3001eflag\u30ec\u30b8\u30b9\u30bf\u306e\u4e2d\u306eIF\u30d5\u30e9\u30b0\u3092\u901a\u3057\u3066\u3001\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u53d6\u308a\u305f\u3044\u304b\u3069\u3046\u304b\u3092\u5236\u5fa1\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<br \/>\ncli\u547d\u4ee4\u306f\u3001IF\u3092\u30af\u30ea\u30a2\u3059\u308b\u4e8b\u306b\u3088\u3063\u3066\u305d\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3078\u306e\u5272\u308a\u8fbc\u307f\u3092\u7121\u52b9\u5316\u3057\u3001sti\u547d\u4ee4\u306f\u305d\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3078\u306e\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u5316\u3059\u308b\u3002<br \/>\nxv6\u306f\u3001\u8d77\u52d5\u4e2d\u306f\u3001\u30e1\u30a4\u30f3CPU\u3068\u4ed6\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5bfe\u3059\u308b\u5272\u308a\u8fbc\u307f\u3092cli\u547d\u4ee4\u3092\u4f7f\u3063\u3066\u7121\u52b9\u5316\u3059\u308b\u3002<br \/>\n\uff08\u30b9\u30da\u30fc\u30b9\u306e\u90fd\u5408\u3068\u305d\u306e\u5185\u5bb9\u306f\u4eca\u306f\u91cd\u8981\u3058\u3083\u306a\u3044\u306e\u3067\u30bd\u30fc\u30b9\u306f\u8f09\u305b\u307e\u305b\u3093\u304c\u305d\u308c\u305e\u308c\u3001bootasm.S\u3001entryother.S\u3067cli\u547d\u4ee4\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002\uff09<br \/>\n\u305d\u308c\u305e\u308c\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u306e\u30b9\u30b1\u30b8\u30e5\u30fc\u30e9\u304c\u3001\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3059\u308b\u3002<br \/>\n\uff08\u3053\u3061\u3089\u3082\u30bd\u30fc\u30b9\u306f\u8f09\u305b\u307e\u305b\u3093\u304c\u3001proc.c\u306escheduler\u95a2\u6570\u3067sti\u547d\u4ee4\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002\uff09<br \/>\n\u7279\u5b9a\u306e\u30b3\u30fc\u30c9\u306e\u65ad\u7247\u3092\u5272\u308a\u8fbc\u307f\u3055\u308c\u306a\u3044\u3088\u3046\u5236\u5fa1\u3059\u308b\u305f\u3081\u3001xv6\u306f\u305d\u308c\u3089\u306e\u30b3\u30fc\u30c9\u306e\u65ad\u7247\u306e\u9593\u3001\u5272\u308a\u8fbc\u307f\u3092\u7121\u52b9\u5316\u3059\u308b\u3002<br \/>\n\uff08\u4f8b\u3048\u3070\u3001switchuvm\u3092\u898b\u3088\uff09<br \/>\n\uff08pushcli\u95a2\u6570\u3001popcli\u95a2\u6570\u306e\u4e2d\u3067\u305d\u308c\u305e\u308ccli\u547d\u4ee4\u3001sti\u547d\u4ee4\u304c\u547c\u3070\u308c\u307e\u3059\u3002\uff09<\/p>\n<p>vm.c\u306eswitchuvm\u95a2\u6570<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Switch TSS and h\/w page table to correspond to process p.\nvoid\nswitchuvm(struct proc *p)\n{\n  pushcli();\n  cpu-&gt;gdt&#x5B;SEG_TSS] = SEG16(STS_T32A, &amp;cpu-&gt;ts, sizeof(cpu-&gt;ts)-1, 0);\n  cpu-&gt;gdt&#x5B;SEG_TSS].s = 0;\n  cpu-&gt;ts.ss0 = SEG_KDATA &lt;&lt; 3;\n  cpu-&gt;ts.esp0 = (uint)proc-&gt;kstack + KSTACKSIZE;\n  ltr(SEG_TSS &lt;&lt; 3);\n  if(p-&gt;pgdir == 0)\n    panic(&quot;switchuvm: no pgdir&quot;);\n  lcr3(v2p(p-&gt;pgdir));  \/\/ switch to new address space\n  popcli();\n}<\/pre>\n<p>\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u306f\u3001\u30d9\u30af\u30bf32\uff08xv6\u304cIRQ 0\u3092\u5236\u5fa1\u3059\u308b\u305f\u3081\u306b\u9078\u3093\u3060\uff09\u3092\u901a\u308a\u3001xv6\u306fidtinit\u95a2\u6570\u306e\u4e2d\u3067\u30bb\u30c3\u30c8\u30a2\u30d7\u3059\u308b\u3002<br \/>\n\uff08idtinit\u95a2\u6570\u306f\u6700\u7d42\u7684\u306blidt\u547d\u4ee4\u3092\u5b9f\u884c\u3059\u308b\uff09<br \/>\n\u30d9\u30af\u30bf32\u3068\u30d9\u30af\u30bf64\uff08\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u7528\uff09\u306e\u9055\u3044\u306f\u3001\u30d9\u30af\u30bf32\u306f\u30c8\u30e9\u30c3\u30d7\u30b2\u30fc\u30c8\u3067\u306f\u306a\u304f\u5272\u308a\u8fbc\u307f\u30b2\u30fc\u30c8\u3067\u3042\u308b\u3068\u3044\u3046\u4e8b\u3060\u3051\u3067\u3042\u308b\u3002<br \/>\n\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u305f\u30d7\u30ed\u30bb\u30c3\u30b5\u304c\u3001\u73fe\u5728\u306e\u5272\u308a\u8fbc\u307f\u3092\u5236\u5fa1\u3057\u3066\u3044\u308b\u9593\u306b\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u306a\u3044\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u306b\u3001\u5272\u308a\u8fbc\u307f\u30b2\u30fc\u30c8\u306fIF\u30d5\u30e9\u30b0\u3092\u30af\u30ea\u30a2\u3059\u308b\u3002<br \/>\n\u3053\u3053\u304b\u3089trap\u95a2\u6570\u306b\u81f3\u308b\u307e\u3067\u3001\u5272\u308a\u8fbc\u307f\u306f\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u3084\u4f8b\u5916\u3084\u3001\u30c8\u30e9\u30c3\u30d7\u30d5\u30ec\u30fc\u30e0\u306e\u69cb\u7bc9\u3068\u540c\u3058\u30b3\u30fc\u30c9\u30d1\u30b9\u3092\u305f\u3069\u308b\u3002<\/p>\n<p>main.c\u306empmain\u95a2\u6570\uff08idtinit\u95a2\u6570\u3092\u547c\u3073\u51fa\u3059\u90e8\u5206\uff09<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Common CPU setup code.\nstatic void\nmpmain(void)\n{\n  cprintf(&quot;cpu%d: starting\\n&quot;, cpu-&gt;id);\n  idtinit();       \/\/ load idt register\n  xchg(&amp;cpu-&gt;started, 1); \/\/ tell startothers() we&#039;re up\n  scheduler();     \/\/ start running processes\n}<\/pre>\n<p>\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3067\u547c\u3070\u308c\u305f\u3068\u304d\u3001trap\u95a2\u6570\u306f\u30012\u3064\u306e\u4e8b\u3060\u3051\u3092\u884c\u3046\u3002<br \/>\n\u5909\u6570ticks\u306e\u30a4\u30f3\u30af\u30ea\u30e1\u30f3\u30c8\u3002<br \/>\nwakeup\u95a2\u6570\u306e\u547c\u3073\u51fa\u3057\u3002<br \/>\n\u7b2c4\u7ae0\u3067\u898b\u308b\u304c\u3001\u5f8c\u8005\u306f\u9055\u3046\u30d7\u30ed\u30bb\u30b9\u3078\u623b\u308b\u5272\u308a\u8fbc\u307f\u3092\u5f15\u304d\u8d77\u3053\u3059\u3002<\/p>\n<p>trap.c\u306etrap\u95a2\u6570\u306e\u30bf\u30a4\u30de\u30fc\u95a2\u9023\u306e\u51e6\u7406\u306e\u90e8\u5206<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">  switch(tf-&gt;trapno){\n  case T_IRQ0 + IRQ_TIMER:\n    if(cpu-&gt;id == 0){\n      acquire(&amp;tickslock);\n      ticks++;\n      wakeup(&amp;ticks);\n      release(&amp;tickslock);\n    }\n    lapiceoi();\n    break;<\/pre>\n<h3>\u611f\u60f3<\/h3>\n<p>\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u4f8b\u306b\u3057\u305f\u5272\u308a\u8fbc\u307f\u306e\u8aac\u660e\u3068\u3044\u3063\u305f\u3068\u3053\u308d\u3067\u3059\u304b\u306d\u3002<br \/>\n\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3082\u304b\u306a\u308a\u91cd\u8981\u306a\u306e\u3067\u3001\u4f8b\u3068\u3044\u3046\u306e\u306f\u3061\u3087\u3063\u3068\u8a00\u3044\u904e\u304e\u3067\u3059\u306d\u3002<\/p>\n<p>\u30d9\u30af\u30bf\u3068\u3044\u3046\u306e\u306f\u3001\u524d\u3005\u3005\u56deCode: Assembly trap handlers\u306e\u7bc0\u306e\u6700\u521d\u306b\u51fa\u3066\u304d\u305f\u3001xv6\u306b\u304a\u3051\u308b\u5272\u308a\u8fbc\u307f\u306e\u533a\u5225\u306e\u70ba\u306e\u6982\u5ff5\u3067\u3059\u306d\u3002<br \/>\n\u5b9f\u969b\u306f\u305f\u3060\u306e\u95a2\u6570\u306e\u914d\u5217\u306e\u3088\u3046\u306a\u3082\u306e\u3067\u3057\u305f\u3002<\/p>\n<p>\u500b\u5225\u306e\u7bc0\u306e\u7406\u89e3\u5ea6\u306f\u5c11\u3057\u3065\u3064\u4e0a\u304c\u3063\u3066\u304d\u3066\u308b\u6c17\u304c\u3057\u307e\u3059\u3002<br \/>\n\u305d\u308c\u305e\u308c\u306e\u95a2\u9023\u3084\u5168\u4f53\u306e\u4e2d\u3067\u3069\u3053\u306b\u4f4d\u7f6e\u3059\u308b\u306e\u304b\u304c\u30d4\u30f3\u3068\u6765\u308b\u3088\u3046\u306b\u306a\u308c\u3070\u3082\u3063\u3068\u7406\u89e3\u304c\u6df1\u307e\u308b\u3093\u3058\u3083\u306a\u3044\u304b\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u30c6\u30ad\u30b9\u30c8\u306e37\u301c39\u30da\u30fc\u30b8<\/p>\n<h3>\u672c\u6587<\/h3>\n<p>\u30de\u30b6\u30fc\u30dc\u30fc\u30c9\u4e0a\u306e\u30c7\u30d0\u30a4\u30b9\u306f\u3001\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u3001xv6\u306f\u305d\u308c\u3089\u306e\u5272\u308a\u8fbc\u307f\u3092\u5236\u5fa1\u3059\u308b\u305f\u3081\u306b\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3002<br \/>\n\u30c7\u30d0\u30a4\u30b9\u306e\u30b5\u30dd\u30fc\u30c8\u7121\u3057\u3067\u306f\u3001xv6\u306f\u4f7f\u3044\u7269\u306b\u306a\u3089\u306a\u3044\u3060\u308d\u3046\u3002<br \/>\n\u30e6\u30fc\u30b6\u306f\u30ad\u30fc\u30dc\u30fc\u30c9\u3067\u30bf\u30a4\u30d7\u51fa\u6765\u306a\u3044\u3057\u3001\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306f\u30c7\u30a3\u30b9\u30af\u306b\u30c7\u30fc\u30bf\u3092\u4fdd\u7ba1\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u306a\u3044\u3057\u3001\u4ed6\u306b\u3082\u305f\u304f\u3055\u3093\u306e\u554f\u984c\u304c\u8d77\u304d\u308b\u3002<br \/>\n\u5e78\u3044\u306b\u3082\u3001\u5272\u308a\u8fbc\u307f\u3092\u8ffd\u52a0\u3057\u305f\u308a\u3001\u5358\u7d14\u306a\u30c7\u30d0\u30a4\u30b9\u3092\u30b5\u30dd\u30fc\u30c8\u3059\u308b\u4e8b\u306f\u3001\u96e3\u3057\u304f\u306a\u3044\u3002<br \/>\n\u4eca\u307e\u3067\u898b\u3066\u304d\u305f\u3088\u3046\u306b\u3001\u5272\u308a\u8fbc\u307f\u306f\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u3068\u4f8b\u5916\u306e\u305f\u3081\u306e\u30b3\u30fc\u30c9\u3068\u540c\u3058\u3082\u306e\u6d41\u7528\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<\/p>\n<p>\u5272\u308a\u8fbc\u307f\u306f\u3001\u3044\u3064\u3067\u3082\u30c7\u30d0\u30a4\u30b9\u306b\u751f\u6210\u3055\u308c\u5f97\u308b\u3068\u3044\u3046\u4e8b\u3092\u9664\u3044\u3066\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u306b\u4f3c\u3066\u3044\u308b\u3002<br \/>\n\u30de\u30b6\u30fc\u30dc\u30fc\u30c9\u4e0a\u306b\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306b\u6ce8\u610f\u304c\u5fc5\u8981\u306a\u3068\u304d\uff08\u4f8b\u3048\u3070\u30e6\u30fc\u30b6\u304c\u30ad\u30fc\u30dc\u30fc\u30c9\u306e\u6587\u5b57\u3092\u30bf\u30a4\u30d7\u3057\u305f\u3068\u304d\uff09\u306bCPU\u3078\u4fe1\u53f7\u3092\u9001\u308b\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u304c\u3042\u308b\u3002<br \/>\n\u6211\u3005\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306b\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3055\u305b\u3001CPU\u304c\u53d7\u3051\u53d6\u308b\u5272\u308a\u8fbc\u307f\u3092\u6574\u5099\u3059\u308b\u305f\u3081\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3002<\/p>\n<p>\u30bf\u30a4\u30de\u30fc\u30c7\u30d0\u30a4\u30b9\u3068\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u898b\u3066\u307f\u3088\u3046\u3002<br \/>\n\u6211\u3005\u306f\u3001\u30ab\u30fc\u30cd\u30eb\u304c\u6642\u9593\u306e\u7d4c\u904e\u3092\u8a8d\u8b58\u51fa\u6765\u308b\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u3001\u30ab\u30fc\u30cd\u30eb\u304c\u8907\u6570\u306e\u30d7\u30ed\u30bb\u30b9\u306e\u9593\u3067\u6642\u5206\u5272\u51fa\u6765\u308b\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u3001\u30bf\u30a4\u30de\u30fc\u30cf\u30fc\u30c9\u30a6\u30a7\u30a2\u306b1\u79d2\u9593\u306b100\u56de\u306e\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3057\u3066\u6b32\u3057\u3044\u3002<br \/>\n1\u79d2\u9593\u306b100\u56de\u3068\u3044\u3046\u9078\u629e\u306f\u3001\u30d7\u30ed\u30bb\u30c3\u30b5\u304c\u5272\u308a\u8fbc\u307f\u306e\u5236\u5fa1\u306b\u5fd9\u6bba\u3055\u308c\u3066\u306a\u3044\u9593\u3001\u9069\u6b63\u306a\u5bfe\u8a71\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u53ef\u80fd\u306b\u3059\u308b\u3002<\/p>\n<p>x86\u30d7\u30ed\u30bb\u30c3\u30b5\u305d\u308c\u81ea\u8eab\u306e\u3088\u3046\u306b\u3001PC\u306e\u30de\u30b6\u30fc\u30dc\u30fc\u30c9\u306f\u9032\u5316\u3057\u3066\u304d\u305f\u3002<br \/>\n\u305d\u3057\u3066\u3001\u63d0\u4f9b\u3055\u308c\u308b\u5272\u308a\u8fbc\u307f\u306e\u65b9\u6cd5\u3082\u540c\u3058\u304f\u9032\u5316\u3057\u3066\u304d\u305f\u3002<br \/>\n\u521d\u671f\u306e\u30dc\u30fc\u30c9\u306f\u3001\u5358\u7d14\u306a\u30d7\u30ed\u30b0\u30e9\u30e0\u53ef\u80fd\u306a\u5272\u308a\u8fbc\u307f\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\uff08PIC\u3068\u547c\u3070\u308c\u308b\uff09\u3092\u6301\u3063\u3066\u3044\u305f\u3002<br \/>\n\u305d\u308c\u3092\u7ba1\u7406\u3059\u308b\u305f\u3081\u306e\u30b3\u30fc\u30c9\u3092picirq.c\u3067\u898b\u3064\u3051\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3060\u308d\u3046\u3002<\/p>\n<p>picirq.c\uff08\u4e00\u5fdc\u8f09\u305b\u3068\u304d\u307e\u3059\uff09<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Intel 8259A programmable interrupt controllers.\n\n#include &quot;types.h&quot;\n#include &quot;x86.h&quot;\n#include &quot;traps.h&quot;\n\n\/\/ I\/O Addresses of the two programmable interrupt controllers\n#define IO_PIC1         0x20    \/\/ Master (IRQs 0-7)\n#define IO_PIC2         0xA0    \/\/ Slave (IRQs 8-15)\n\n#define IRQ_SLAVE       2       \/\/ IRQ at which slave connects to master\n\n\/\/ Current IRQ mask.\n\/\/ Initial IRQ mask has interrupt 2 enabled (for slave 8259A).\nstatic ushort irqmask = 0xFFFF &amp; ~(1&lt;&lt;IRQ_SLAVE);\n\nstatic void\npicsetmask(ushort mask)\n{\n  irqmask = mask;\n  outb(IO_PIC1+1, mask);\n  outb(IO_PIC2+1, mask &gt;&gt; 8);\n}\n\nvoid\npicenable(int irq)\n{\n  picsetmask(irqmask &amp; ~(1&lt;&lt;irq));\n}\n\n\/\/ Initialize the 8259A interrupt controllers.\nvoid\npicinit(void)\n{\n  \/\/ mask all interrupts\n  outb(IO_PIC1+1, 0xFF);\n  outb(IO_PIC2+1, 0xFF);\n\n  \/\/ Set up master (8259A-1)\n\n  \/\/ ICW1:  0001g0hi\n  \/\/    g:  0 = edge triggering, 1 = level triggering\n  \/\/    h:  0 = cascaded PICs, 1 = master only\n  \/\/    i:  0 = no ICW4, 1 = ICW4 required\n  outb(IO_PIC1, 0x11);\n\n  \/\/ ICW2:  Vector offset\n  outb(IO_PIC1+1, T_IRQ0);\n\n  \/\/ ICW3:  (master PIC) bit mask of IR lines connected to slaves\n  \/\/        (slave PIC) 3-bit # of slave&#039;s connection to master\n  outb(IO_PIC1+1, 1&lt;&lt;IRQ_SLAVE);\n\n  \/\/ ICW4:  000nbmap\n  \/\/    n:  1 = special fully nested mode\n  \/\/    b:  1 = buffered mode\n  \/\/    m:  0 = slave PIC, 1 = master PIC\n  \/\/      (ignored when b is 0, as the master\/slave role\n  \/\/      can be hardwired).\n  \/\/    a:  1 = Automatic EOI mode\n  \/\/    p:  0 = MCS-80\/85 mode, 1 = intel x86 mode\n  outb(IO_PIC1+1, 0x3);\n\n  \/\/ Set up slave (8259A-2)\n  outb(IO_PIC2, 0x11);                  \/\/ ICW1\n  outb(IO_PIC2+1, T_IRQ0 + 8);      \/\/ ICW2\n  outb(IO_PIC2+1, IRQ_SLAVE);           \/\/ ICW3\n  \/\/ NB Automatic EOI mode doesn&#039;t tend to work on the slave.\n  \/\/ Linux source code says it&#039;s &quot;to be investigated&quot;.\n  outb(IO_PIC2+1, 0x3);                 \/\/ ICW4\n\n  \/\/ OCW3:  0ef01prs\n  \/\/   ef:  0x = NOP, 10 = clear specific mask, 11 = set specific mask\n  \/\/    p:  0 = no polling, 1 = polling mode\n  \/\/   rs:  0x = NOP, 10 = read IRR, 11 = read ISR\n  outb(IO_PIC1, 0x68);             \/\/ clear specific mask\n  outb(IO_PIC1, 0x0a);             \/\/ read IRR by default\n\n  outb(IO_PIC2, 0x68);             \/\/ OCW3\n  outb(IO_PIC2, 0x0a);             \/\/ OCW3\n\n  if(irqmask != 0xFFFF)\n    picsetmask(irqmask);\n}&amp;#91;\/sourcecode&amp;#93;\n\n\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30c3\u30b5PC\u30dc\u30fc\u30c9\u306e\u767b\u5834\u306b\u3088\u3063\u3066\u3001\u65b0\u3057\u3044\u5272\u308a\u8fbc\u307f\u306e\u5236\u5fa1\u65b9\u6cd5\u304c\u5fc5\u8981\u3068\u3055\u308c\u305f\u3002\n\u306a\u305c\u306a\u3089\u3001\u3069\u306eCPU\u3082\u5272\u308a\u8fbc\u307f\u3092\u5236\u5fa1\u3059\u308b\u305f\u3081\u306e\u5272\u308a\u8fbc\u307f\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u3092\u5fc5\u8981\u3068\u3057\u3001\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5bfe\u3059\u308b\u30eb\u30fc\u30c1\u30f3\u5272\u308a\u8fbc\u307f\u306e\u70ba\u306e\u624b\u6cd5\u304c\u5b58\u5728\u3059\u3079\u304d\u3060\u304b\u3089\u3067\u3042\u308b\u3002\n\u3053\u306e\u65b9\u6cd5\u306f\u30012\u3064\u306e\u90e8\u5206\u304b\u3089\u6210\u308b\u3002\n1\u3064\u306f\u3001I\/O\u30b7\u30b9\u30c6\u30e0\u90e8\u5206\uff08IO APIC, ioapic.c\uff09\u3001\u3082\u30461\u3064\u306f\u3001\u305d\u308c\u305e\u308c\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u30a2\u30bf\u30c3\u30c1\u3059\u308b\u90e8\u5206\uff08\u30ed\u30fc\u30ab\u30ebAPIC, lapic.c\uff09\u3067\u3042\u308b\u3002\nxv6\u306f\u3001\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30c3\u30b5\u7528\u306e\u30dc\u30fc\u30c9\u306e\u305f\u3081\u306b\u30c7\u30b6\u30a4\u30f3\u3055\u308c\u3001\u305d\u3057\u3066\u3069\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3082\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u53d6\u308b\u305f\u3081\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3055\u308c\u308b\u3002\n\nioapic.c\n&amp;#91;sourcecode language=&quot;c&quot;&amp;#93;\/\/ The I\/O APIC manages hardware interrupts for an SMP system.\n\/\/ http:\/\/www.intel.com\/design\/chipsets\/datashts\/29056601.pdf\n\/\/ See also picirq.c.\n\n#include &quot;types.h&quot;\n#include &quot;defs.h&quot;\n#include &quot;traps.h&quot;\n\n#define IOAPIC  0xFEC00000   \/\/ Default physical address of IO APIC\n\n#define REG_ID     0x00  \/\/ Register index: ID\n#define REG_VER    0x01  \/\/ Register index: version\n#define REG_TABLE  0x10  \/\/ Redirection table base\n\n\/\/ The redirection table starts at REG_TABLE and uses\n\/\/ two registers to configure each interrupt.  \n\/\/ The first (low) register in a pair contains configuration bits.\n\/\/ The second (high) register contains a bitmask telling which\n\/\/ CPUs can serve that interrupt.\n#define INT_DISABLED   0x00010000  \/\/ Interrupt disabled\n#define INT_LEVEL      0x00008000  \/\/ Level-triggered (vs edge-)\n#define INT_ACTIVELOW  0x00002000  \/\/ Active low (vs high)\n#define INT_LOGICAL    0x00000800  \/\/ Destination is CPU id (vs APIC ID)\n\nvolatile struct ioapic *ioapic;\n\n\/\/ IO APIC MMIO structure: write reg, then read or write data.\nstruct ioapic {\n  uint reg;\n  uint pad&amp;#91;3&amp;#93;;\n  uint data;\n};\n\nstatic uint\nioapicread(int reg)\n{\n  ioapic-&gt;reg = reg;\n  return ioapic-&gt;data;\n}\n\nstatic void\nioapicwrite(int reg, uint data)\n{\n  ioapic-&gt;reg = reg;\n  ioapic-&gt;data = data;\n}\n\nvoid\nioapicinit(void)\n{\n  int i, id, maxintr;\n\n  if(!ismp)\n    return;\n\n  ioapic = (volatile struct ioapic*)IOAPIC;\n  maxintr = (ioapicread(REG_VER) &gt;&gt; 16) &amp; 0xFF;\n  id = ioapicread(REG_ID) &gt;&gt; 24;\n  if(id != ioapicid)\n    cprintf(&quot;ioapicinit: id isn&#039;t equal to ioapicid; not a MP\\n&quot;);\n\n  \/\/ Mark all interrupts edge-triggered, active high, disabled,\n  \/\/ and not routed to any CPUs.\n  for(i = 0; i &lt;= maxintr; i++){\n    ioapicwrite(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i));\n    ioapicwrite(REG_TABLE+2*i+1, 0);\n  }\n}\n\nvoid\nioapicenable(int irq, int cpunum)\n{\n  if(!ismp)\n    return;\n\n  \/\/ Mark interrupt edge-triggered, active high,\n  \/\/ enabled, and routed to the given cpunum,\n  \/\/ which happens to be that cpu&#039;s APIC ID.\n  ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq);\n  ioapicwrite(REG_TABLE+2*irq+1, cpunum &lt;&lt; 24);\n}&amp;#91;\/sourcecode&amp;#93;\n\nlapic.c\n&amp;#91;sourcecode language=&quot;c&quot;&amp;#93;\/\/ The local APIC manages internal (non-I\/O) interrupts.\n\/\/ See Chapter 8 &amp; Appendix C of Intel processor manual volume 3.\n\n#include &quot;types.h&quot;\n#include &quot;defs.h&quot;\n#include &quot;memlayout.h&quot;\n#include &quot;traps.h&quot;\n#include &quot;mmu.h&quot;\n#include &quot;x86.h&quot;\n\n\/\/ Local APIC registers, divided by 4 for use as uint&amp;#91;&amp;#93; indices.\n#define ID      (0x0020\/4)   \/\/ ID\n#define VER     (0x0030\/4)   \/\/ Version\n#define TPR     (0x0080\/4)   \/\/ Task Priority\n#define EOI     (0x00B0\/4)   \/\/ EOI\n#define SVR     (0x00F0\/4)   \/\/ Spurious Interrupt Vector\n  #define ENABLE     0x00000100   \/\/ Unit Enable\n#define ESR     (0x0280\/4)   \/\/ Error Status\n#define ICRLO   (0x0300\/4)   \/\/ Interrupt Command\n  #define INIT       0x00000500   \/\/ INIT\/RESET\n  #define STARTUP    0x00000600   \/\/ Startup IPI\n  #define DELIVS     0x00001000   \/\/ Delivery status\n  #define ASSERT     0x00004000   \/\/ Assert interrupt (vs deassert)\n  #define DEASSERT   0x00000000\n  #define LEVEL      0x00008000   \/\/ Level triggered\n  #define BCAST      0x00080000   \/\/ Send to all APICs, including self.\n  #define BUSY       0x00001000\n  #define FIXED      0x00000000\n#define ICRHI   (0x0310\/4)   \/\/ Interrupt Command &amp;#91;63:32&amp;#93;\n#define TIMER   (0x0320\/4)   \/\/ Local Vector Table 0 (TIMER)\n  #define X1         0x0000000B   \/\/ divide counts by 1\n  #define PERIODIC   0x00020000   \/\/ Periodic\n#define PCINT   (0x0340\/4)   \/\/ Performance Counter LVT\n#define LINT0   (0x0350\/4)   \/\/ Local Vector Table 1 (LINT0)\n#define LINT1   (0x0360\/4)   \/\/ Local Vector Table 2 (LINT1)\n#define ERROR   (0x0370\/4)   \/\/ Local Vector Table 3 (ERROR)\n  #define MASKED     0x00010000   \/\/ Interrupt masked\n#define TICR    (0x0380\/4)   \/\/ Timer Initial Count\n#define TCCR    (0x0390\/4)   \/\/ Timer Current Count\n#define TDCR    (0x03E0\/4)   \/\/ Timer Divide Configuration\n\nvolatile uint *lapic;  \/\/ Initialized in mp.c\n\nstatic void\nlapicw(int index, int value)\n{\n  lapic&amp;#91;index&amp;#93; = value;\n  lapic&amp;#91;ID&amp;#93;;  \/\/ wait for write to finish, by reading\n}\n\/\/PAGEBREAK!\n\nvoid\nlapicinit(int c)\n{\n  if(!lapic) \n    return;\n\n  \/\/ Enable local APIC; set spurious interrupt vector.\n  lapicw(SVR, ENABLE | (T_IRQ0 + IRQ_SPURIOUS));\n\n  \/\/ The timer repeatedly counts down at bus frequency\n  \/\/ from lapic&amp;#91;TICR&amp;#93; and then issues an interrupt.  \n  \/\/ If xv6 cared more about precise timekeeping,\n  \/\/ TICR would be calibrated using an external time source.\n  lapicw(TDCR, X1);\n  lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));\n  lapicw(TICR, 10000000); \n\n  \/\/ Disable logical interrupt lines.\n  lapicw(LINT0, MASKED);\n  lapicw(LINT1, MASKED);\n\n  \/\/ Disable performance counter overflow interrupts\n  \/\/ on machines that provide that interrupt entry.\n  if(((lapic&amp;#91;VER&amp;#93;&gt;&gt;16) &amp; 0xFF) &gt;= 4)\n    lapicw(PCINT, MASKED);\n\n  \/\/ Map error interrupt to IRQ_ERROR.\n  lapicw(ERROR, T_IRQ0 + IRQ_ERROR);\n\n  \/\/ Clear error status register (requires back-to-back writes).\n  lapicw(ESR, 0);\n  lapicw(ESR, 0);\n\n  \/\/ Ack any outstanding interrupts.\n  lapicw(EOI, 0);\n\n  \/\/ Send an Init Level De-Assert to synchronise arbitration ID&#039;s.\n  lapicw(ICRHI, 0);\n  lapicw(ICRLO, BCAST | INIT | LEVEL);\n  while(lapic&#x5B;ICRLO] &amp; DELIVS)\n    ;\n\n  \/\/ Enable interrupts on the APIC (but not on the processor).\n  lapicw(TPR, 0);\n}\n\nint\ncpunum(void)\n{\n  \/\/ Cannot call cpu when interrupts are enabled:\n  \/\/ result not guaranteed to last long enough to be used!\n  \/\/ Would prefer to panic but even printing is chancy here:\n  \/\/ almost everything, including cprintf and panic, calls cpu,\n  \/\/ often indirectly through acquire and release.\n  if(readeflags()&amp;FL_IF){\n    static int n;\n    if(n++ == 0)\n      cprintf(&quot;cpu called from %x with interrupts enabled\\n&quot;,\n        __builtin_return_address(0));\n  }\n\n  if(lapic)\n    return lapic&#x5B;ID]&gt;&gt;24;\n  return 0;\n}\n\n\/\/ Acknowledge interrupt.\nvoid\nlapiceoi(void)\n{\n  if(lapic)\n    lapicw(EOI, 0);\n}\n\n\/\/ Spin for a given number of microseconds.\n\/\/ On real hardware would want to tune this dynamically.\nvoid\nmicrodelay(int us)\n{\n}\n\n#define IO_RTC  0x70\n\n\/\/ Start additional processor running entry code at addr.\n\/\/ See Appendix B of MultiProcessor Specification.\nvoid\nlapicstartap(uchar apicid, uint addr)\n{\n  int i;\n  ushort *wrv;\n  \n  \/\/ &quot;The BSP must initialize CMOS shutdown code to 0AH\n  \/\/ and the warm reset vector (DWORD based at 40:67) to point at\n  \/\/ the AP startup code prior to the &#x5B;universal startup algorithm].&quot;\n  outb(IO_RTC, 0xF);  \/\/ offset 0xF is shutdown code\n  outb(IO_RTC+1, 0x0A);\n  wrv = (ushort*)P2V((0x40&lt;&lt;4 | 0x67));  \/\/ Warm reset vector\n  wrv&amp;#91;0&amp;#93; = 0;\n  wrv&amp;#91;1&amp;#93; = addr &gt;&gt; 4;\n\n  \/\/ &quot;Universal startup algorithm.&quot;\n  \/\/ Send INIT (level-triggered) interrupt to reset other CPU.\n  lapicw(ICRHI, apicid&lt;&lt;24);\n  lapicw(ICRLO, INIT | LEVEL | ASSERT);\n  microdelay(200);\n  lapicw(ICRLO, INIT | LEVEL);\n  microdelay(100);    \/\/ should be 10ms, but too slow in Bochs!\n  \n  \/\/ Send startup IPI (twice!) to enter code.\n  \/\/ Regular hardware is supposed to only accept a STARTUP\n  \/\/ when it is in the halted state due to an INIT.  So the second\n  \/\/ should be ignored, but it is part of the official Intel algorithm.\n  \/\/ Bochs complains about the second one.  Too bad for Bochs.\n  for(i = 0; i &lt; 2; i++){\n    lapicw(ICRHI, apicid&lt;&lt;24);\n    lapicw(ICRLO, STARTUP | (addr&gt;&gt;12));\n    microdelay(200);\n  }\n}<\/pre>\n<p>\u30e6\u30cb\u30d7\u30ed\u30bb\u30c3\u30b5\u4e0a\u3067\u3082\u3061\u3083\u3093\u3068\u52d5\u304f\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u306b\u3001xv6\u306f\u3001\u30d7\u30ed\u30b0\u30e9\u30e0\u53ef\u80fd\u306a\u5272\u308a\u8fbc\u307f\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\uff08PIC\uff09\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002<br \/>\n\uff08picirq.c\u306epicinit\u95a2\u6570\uff09<br \/>\n\u3069\u306ePIC\u3082\u6700\u5927\u30678\u500b\u306e\u5272\u308a\u8fbc\u307f\uff08\u4f8b\u3048\u3070\u8907\u6570\u306e\u30c7\u30d0\u30a4\u30b9\uff09\u3092\u5236\u5fa1\u51fa\u6765\u3001\u305d\u3057\u3066\u305d\u308c\u3089\u3092\u30d7\u30ed\u30bb\u30c3\u30b5\u306e\u5272\u308a\u8fbc\u307f\u30d4\u30f3\u3078\u591a\u91cd\u9001\u4fe1\u3059\u308b\u3002<br \/>\n8\u500b\u4ee5\u4e0a\u306e\u30c7\u30d0\u30a4\u30b9\u306b\u5bfe\u5fdc\u3059\u308b\u305f\u3081\u3001\u8907\u6570\u306ePIC\u306f\u30ab\u30b9\u30b1\u30fc\u30c9\u63a5\u7d9a\u3055\u308c\u3001\u5178\u578b\u7684\u306a\u30dc\u30fc\u30c9\u306a\u3089\u6700\u4f4e\u3067\u30822\u3064\u306ePIC\u3092\u6301\u3064\u3002<br \/>\ninb\u547d\u4ee4\u3068outb\u547d\u4ee4\u3092\u4f7f\u3046\u3053\u3068\u3067\u3001xv6\u306f\u3001\u30de\u30b9\u30bf\u306bIRQ 0\u304b\u3089IRQ 7\u3092\u751f\u6210\u3055\u305b\u308b\u305f\u3081\u3001\u30b9\u30ec\u30fc\u30d6\u306bIRQ 8\u304b\u3089IRQ 15\uff08\u539f\u6587\u3067\u306f16\u306b\u306a\u3063\u3066\u308b\uff09\u3092\u751f\u6210\u3055\u305b\u308b\u305f\u3081\u306b\u3001\u305d\u308c\u3089\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002<br \/>\n\u6700\u521d\u306b\u3001xv6\u306fPIC\u306b\u5168\u3066\u306e\u5272\u308a\u8fbc\u307f\u3092\u30de\u30b9\u30af\u3055\u305b\u308b\u305f\u3081\u306b\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002<br \/>\ntimer.c\u306e\u30b3\u30fc\u30c9\u3067\u3001\u30bf\u30a4\u30de\u30fc\u30921\u306b\u30bb\u30c3\u30c8\u3057PIC\u4e0a\u306e\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3057\u3066\u3044\u308b\u3002<br \/>\n\uff08timer.c\u306etimerinit\u95a2\u6570\uff09<br \/>\n\u4eca\u306f\u3001PIC\u306e\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u306b\u95a2\u3057\u3066\u8a73\u7d30\u3092\u3044\u304f\u3064\u304b\u7701\u3044\u3066\u3044\u308b\u3002<br \/>\n\u305d\u308c\u3089\u306e\u8a73\u7d30\uff08PIC\u3001IOAPIC\u3001LAPIC\uff09\u306f\u3001\u3053\u306e\u30c6\u30ad\u30b9\u30c8\u3067\u306f\u91cd\u8981\u3067\u306f\u306a\u3044\u304c\u3001\u8208\u5473\u3092\u6301\u3063\u305f\u8aad\u8005\u306f\u305d\u308c\u3089\u306e\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u3067\u53c2\u7167\u3055\u308c\u3066\u3044\u308b\u305d\u308c\u305e\u308c\u306e\u30c7\u30d0\u30a4\u30b9\u306e\u30de\u30cb\u30e5\u30a2\u30eb\u3092\u8abf\u3079\u308b\u4e8b\u304c\u3067\u304d\u308b\u3002<\/p>\n<p>timer.c<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Intel 8253\/8254\/82C54 Programmable Interval Timer (PIT).\n\/\/ Only used on uniprocessors;\n\/\/ SMP machines use the local APIC timer.\n\n#include \"types.h\"\n#include \"defs.h\"\n#include \"traps.h\"\n#include \"x86.h\"\n\n#define IO_TIMER1       0x040           \/\/ 8253 Timer #1\n\n\/\/ Frequency of all three count-down timers;\n\/\/ (TIMER_FREQ\/freq) is the appropriate count\n\/\/ to generate a frequency of freq Hz.\n\n#define TIMER_FREQ      1193182\n#define TIMER_DIV(x)    ((TIMER_FREQ+(x)\/2)\/(x))\n\n#define TIMER_MODE      (IO_TIMER1 + 3) \/\/ timer mode port\n#define TIMER_SEL0      0x00    \/\/ select counter 0\n#define TIMER_RATEGEN   0x04    \/\/ mode 2, rate generator\n#define TIMER_16BIT     0x30    \/\/ r\/w counter 16 bits, LSB first\n\nvoid\ntimerinit(void)\n{\n  \/\/ Interrupt 100 times\/sec.\n  outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);\n  outb(IO_TIMER1, TIMER_DIV(100) % 256);\n  outb(IO_TIMER1, TIMER_DIV(100) \/ 256);\n  picenable(IRQ_TIMER);\n}<\/pre>\n<p>\u30de\u30eb\u30c1\u30d7\u30ed\u30bb\u30c3\u30b5\u306e\u5834\u5408\u3001xv6\u306f\u3001\u305d\u308c\u305e\u308c\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u4e0a\u3067IOAPIC\u3068LAPIC\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3057\u306a\u3051\u308c\u3070\u306a\u3089\u306a\u3044\u3002<br \/>\nIO APIC\u306f\u30c6\u30fc\u30d6\u30eb\u3092\u6301\u3061\u3001\u30d7\u30ed\u30bb\u30c3\u30b5\u306finb\u547d\u4ee4\u3084outb\u547d\u4ee4\u3092\u4f7f\u3046\u4ee3\u308f\u308a\u306b\u3001\u30e1\u30e2\u30ea\u30de\u30c3\u30d7\u30c9I\/O\u3092\u901a\u3057\u3066\u305d\u306e\u30c6\u30fc\u30d6\u30eb\u306e\u30a8\u30f3\u30c8\u30ea\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<br \/>\n\u521d\u671f\u5316\u4e2d\u3001xv6\u306f\u3001\u5272\u308a\u8fbc\u307f0\u3092IRQ 0\u306b\u5bfe\u5fdc\u4ed8\u3051\u308b\u3088\u3046\u30d7\u30ed\u30b0\u30e9\u30e0\u3059\u308b\u3002\uff081\u4ee5\u964d\u3082\u540c\u69d8\u306b\uff09<br \/>\n\u3057\u304b\u3057\u3001\u305d\u308c\u3089\u5168\u3066\u3092\u7121\u52b9\u5316\u3059\u308b\u3002<br \/>\n\u7279\u5b9a\u306e\u30c7\u30d0\u30a4\u30b9\u306f\u3001\u7279\u6709\u306e\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3057\u3001\u305d\u306e\u5272\u308a\u8fbc\u307f\u3092\u62c5\u5f53\u3059\u3079\u304d\u3067\u3042\u308b\u3068\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u4f1d\u3048\u308b\u3002<br \/>\n\u4f8b\u3048\u3070\u3001xv6\u306f\u30ad\u30fc\u30dc\u30fc\u30c9\u5272\u308a\u8fbc\u307f\u3092\u30d7\u30ed\u30bb\u30c3\u30b50\u306b\u9001\u308b\u3002<br \/>\n\uff08console.c\u306econsoleinit\u95a2\u6570\uff09<br \/>\n\u5f8c\u3067\u898b\u308b\u304c\u3001xv6\u306f\u30c7\u30a3\u30b9\u30af\u5272\u308a\u8fbc\u307f\u3092\u305d\u306e\u30b7\u30b9\u30c6\u30e0\u3067\u4e00\u756a\u756a\u53f7\u304c\u5927\u304d\u3044\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5272\u308a\u5f53\u3066\u308b\u3002<\/p>\n<p>console.c\u306econsoleinit\u95a2\u6570<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">void\nconsoleinit(void)\n{\n  initlock(&cons.lock, \"console\");\n  initlock(&input.lock, \"input\");\n\n  devsw&#x5B;CONSOLE].write = consolewrite;\n  devsw&#x5B;CONSOLE].read = consoleread;\n  cons.locking = 1;\n\n  picenable(IRQ_KBD);\n  ioapicenable(IRQ_KBD, 0);\n}<\/pre>\n<p>\u30bf\u30a4\u30de\u30fc\u30c1\u30c3\u30d7\u306fLAPIC\u306e\u4e2d\u306b\u3042\u308a\u3001\u305d\u306e\u304a\u304b\u3052\u3067\u3069\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3082\u500b\u5225\u306b\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u53d6\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<br \/>\nxv6\u306f\u3001\u305d\u308c\u3092lapic.c\u306elapicinit\u95a2\u6570\u3067\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3057\u3066\u3044\u308b\u3002<br \/>\n\u91cd\u8981\u306a\u884c\u306f\u3001\u30bf\u30a4\u30de\u30fc\u3092\u30d7\u30ed\u30b0\u30e9\u30e0\u3057\u3066\u308b\u90e8\u5206\u3067\u3042\u308b\u3002<br \/>\n\uff08lapicw(TIMER, PERIODIC | (T_IRQ0 + IRQ_TIMER));\u306e\u90e8\u5206)<br \/>\n\u3053\u306e\u884c\u306f\u3001LAPIC\u306bIRQ_TIMER\u3067\u5272\u308a\u8fbc\u307f\u3092\u751f\u6210\u3055\u305b\u308b\u4e8b\u3092\u4f1d\u3048\u3066\u3044\u308b\u3002<br \/>\n\uff08traps.h\u306b#define IRQ_TIMER 0\u3068\u3042\u308aIRQ 0\u306b\u3042\u305f\u308b\uff09<br \/>\nlapicinit\u306e\u6700\u5f8c\u306e\u884c\uff08lapicw(TPR, 0);\uff09\u306f\u3001\u30ed\u30fc\u30ab\u30eb\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5272\u308a\u8fbc\u307f\u3092\u904b\u3076\u305f\u3081\u306bCPU\u306eLAPIC\u4e0a\u306e\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3059\u308b\u3002<\/p>\n<p>\u30d7\u30ed\u30bb\u30c3\u30b5\u306f\u3001eflag\u30ec\u30b8\u30b9\u30bf\u306e\u4e2d\u306eIF\u30d5\u30e9\u30b0\u3092\u901a\u3057\u3066\u3001\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u53d6\u308a\u305f\u3044\u304b\u3069\u3046\u304b\u3092\u5236\u5fa1\u3059\u308b\u3053\u3068\u304c\u51fa\u6765\u308b\u3002<br \/>\ncli\u547d\u4ee4\u306f\u3001IF\u3092\u30af\u30ea\u30a2\u3059\u308b\u4e8b\u306b\u3088\u3063\u3066\u305d\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3078\u306e\u5272\u308a\u8fbc\u307f\u3092\u7121\u52b9\u5316\u3057\u3001sti\u547d\u4ee4\u306f\u305d\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u3078\u306e\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u5316\u3059\u308b\u3002<br \/>\nxv6\u306f\u3001\u8d77\u52d5\u4e2d\u306f\u3001\u30e1\u30a4\u30f3CPU\u3068\u4ed6\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u306b\u5bfe\u3059\u308b\u5272\u308a\u8fbc\u307f\u3092cli\u547d\u4ee4\u3092\u4f7f\u3063\u3066\u7121\u52b9\u5316\u3059\u308b\u3002<br \/>\n\uff08\u30b9\u30da\u30fc\u30b9\u306e\u90fd\u5408\u3068\u305d\u306e\u5185\u5bb9\u306f\u4eca\u306f\u91cd\u8981\u3058\u3083\u306a\u3044\u306e\u3067\u30bd\u30fc\u30b9\u306f\u8f09\u305b\u307e\u305b\u3093\u304c\u305d\u308c\u305e\u308c\u3001bootasm.S\u3001entryother.S\u3067cli\u547d\u4ee4\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002\uff09<br \/>\n\u305d\u308c\u305e\u308c\u306e\u30d7\u30ed\u30bb\u30c3\u30b5\u306e\u30b9\u30b1\u30b8\u30e5\u30fc\u30e9\u304c\u3001\u5272\u308a\u8fbc\u307f\u3092\u6709\u52b9\u306b\u3059\u308b\u3002<br \/>\n\uff08\u3053\u3061\u3089\u3082\u30bd\u30fc\u30b9\u306f\u8f09\u305b\u307e\u305b\u3093\u304c\u3001proc.c\u306escheduler\u95a2\u6570\u3067sti\u547d\u4ee4\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002\uff09<br \/>\n\u7279\u5b9a\u306e\u30b3\u30fc\u30c9\u306e\u65ad\u7247\u3092\u5272\u308a\u8fbc\u307f\u3055\u308c\u306a\u3044\u3088\u3046\u5236\u5fa1\u3059\u308b\u305f\u3081\u3001xv6\u306f\u305d\u308c\u3089\u306e\u30b3\u30fc\u30c9\u306e\u65ad\u7247\u306e\u9593\u3001\u5272\u308a\u8fbc\u307f\u3092\u7121\u52b9\u5316\u3059\u308b\u3002<br \/>\n\uff08\u4f8b\u3048\u3070\u3001switchuvm\u3092\u898b\u3088\uff09<br \/>\n\uff08pushcli\u95a2\u6570\u3001popcli\u95a2\u6570\u306e\u4e2d\u3067\u305d\u308c\u305e\u308ccli\u547d\u4ee4\u3001sti\u547d\u4ee4\u304c\u547c\u3070\u308c\u307e\u3059\u3002\uff09<\/p>\n<p>vm.c\u306eswitchuvm\u95a2\u6570<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Switch TSS and h\/w page table to correspond to process p.\nvoid\nswitchuvm(struct proc *p)\n{\n  pushcli();\n  cpu-&gt;gdt&#x5B;SEG_TSS] = SEG16(STS_T32A, &amp;cpu-&gt;ts, sizeof(cpu-&gt;ts)-1, 0);\n  cpu-&gt;gdt&#x5B;SEG_TSS].s = 0;\n  cpu-&gt;ts.ss0 = SEG_KDATA &lt;&lt; 3;\n  cpu-&gt;ts.esp0 = (uint)proc-&gt;kstack + KSTACKSIZE;\n  ltr(SEG_TSS &lt;&lt; 3);\n  if(p-&gt;pgdir == 0)\n    panic(&quot;switchuvm: no pgdir&quot;);\n  lcr3(v2p(p-&gt;pgdir));  \/\/ switch to new address space\n  popcli();\n}<\/pre>\n<p>\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u306f\u3001\u30d9\u30af\u30bf32\uff08xv6\u304cIRQ 0\u3092\u5236\u5fa1\u3059\u308b\u305f\u3081\u306b\u9078\u3093\u3060\uff09\u3092\u901a\u308a\u3001xv6\u306fidtinit\u95a2\u6570\u306e\u4e2d\u3067\u30bb\u30c3\u30c8\u30a2\u30d7\u3059\u308b\u3002<br \/>\n\uff08idtinit\u95a2\u6570\u306f\u6700\u7d42\u7684\u306blidt\u547d\u4ee4\u3092\u5b9f\u884c\u3059\u308b\uff09<br \/>\n\u30d9\u30af\u30bf32\u3068\u30d9\u30af\u30bf64\uff08\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u7528\uff09\u306e\u9055\u3044\u306f\u3001\u30d9\u30af\u30bf32\u306f\u30c8\u30e9\u30c3\u30d7\u30b2\u30fc\u30c8\u3067\u306f\u306a\u304f\u5272\u308a\u8fbc\u307f\u30b2\u30fc\u30c8\u3067\u3042\u308b\u3068\u3044\u3046\u4e8b\u3060\u3051\u3067\u3042\u308b\u3002<br \/>\n\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u305f\u30d7\u30ed\u30bb\u30c3\u30b5\u304c\u3001\u73fe\u5728\u306e\u5272\u308a\u8fbc\u307f\u3092\u5236\u5fa1\u3057\u3066\u3044\u308b\u9593\u306b\u5272\u308a\u8fbc\u307f\u3092\u53d7\u3051\u306a\u3044\u3088\u3046\u306b\u3059\u308b\u305f\u3081\u306b\u3001\u5272\u308a\u8fbc\u307f\u30b2\u30fc\u30c8\u306fIF\u30d5\u30e9\u30b0\u3092\u30af\u30ea\u30a2\u3059\u308b\u3002<br \/>\n\u3053\u3053\u304b\u3089trap\u95a2\u6570\u306b\u81f3\u308b\u307e\u3067\u3001\u5272\u308a\u8fbc\u307f\u306f\u3001\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u3084\u4f8b\u5916\u3084\u3001\u30c8\u30e9\u30c3\u30d7\u30d5\u30ec\u30fc\u30e0\u306e\u69cb\u7bc9\u3068\u540c\u3058\u30b3\u30fc\u30c9\u30d1\u30b9\u3092\u305f\u3069\u308b\u3002<\/p>\n<p>main.c\u306empmain\u95a2\u6570\uff08idtinit\u95a2\u6570\u3092\u547c\u3073\u51fa\u3059\u90e8\u5206\uff09<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\/\/ Common CPU setup code.\nstatic void\nmpmain(void)\n{\n  cprintf(&quot;cpu%d: starting\\n&quot;, cpu-&gt;id);\n  idtinit();       \/\/ load idt register\n  xchg(&amp;cpu-&gt;started, 1); \/\/ tell startothers() we&#039;re up\n  scheduler();     \/\/ start running processes\n}<\/pre>\n<p>\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3067\u547c\u3070\u308c\u305f\u3068\u304d\u3001trap\u95a2\u6570\u306f\u30012\u3064\u306e\u4e8b\u3060\u3051\u3092\u884c\u3046\u3002<br \/>\n\u5909\u6570ticks\u306e\u30a4\u30f3\u30af\u30ea\u30e1\u30f3\u30c8\u3002<br \/>\nwakeup\u95a2\u6570\u306e\u547c\u3073\u51fa\u3057\u3002<br \/>\n\u7b2c4\u7ae0\u3067\u898b\u308b\u304c\u3001\u5f8c\u8005\u306f\u9055\u3046\u30d7\u30ed\u30bb\u30b9\u3078\u623b\u308b\u5272\u308a\u8fbc\u307f\u3092\u5f15\u304d\u8d77\u3053\u3059\u3002<\/p>\n<p>trap.c\u306etrap\u95a2\u6570\u306e\u30bf\u30a4\u30de\u30fc\u95a2\u9023\u306e\u51e6\u7406\u306e\u90e8\u5206<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">  switch(tf-&gt;trapno){\n  case T_IRQ0 + IRQ_TIMER:\n    if(cpu-&gt;id == 0){\n      acquire(&amp;tickslock);\n      ticks++;\n      wakeup(&amp;ticks);\n      release(&amp;tickslock);\n    }\n    lapiceoi();\n    break;<\/pre>\n<h3>\u611f\u60f3<\/h3>\n<p>\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3092\u4f8b\u306b\u3057\u305f\u5272\u308a\u8fbc\u307f\u306e\u8aac\u660e\u3068\u3044\u3063\u305f\u3068\u3053\u308d\u3067\u3059\u304b\u306d\u3002<br \/>\n\u30bf\u30a4\u30de\u30fc\u5272\u308a\u8fbc\u307f\u3082\u304b\u306a\u308a\u91cd\u8981\u306a\u306e\u3067\u3001\u4f8b\u3068\u3044\u3046\u306e\u306f\u3061\u3087\u3063\u3068\u8a00\u3044\u904e\u304e\u3067\u3059\u306d\u3002<\/p>\n<p>\u30d9\u30af\u30bf\u3068\u3044\u3046\u306e\u306f\u3001\u524d\u3005\u3005\u56deCode: Assembly trap handlers\u306e\u7bc0\u306e\u6700\u521d\u306b\u51fa\u3066\u304d\u305f\u3001xv6\u306b\u304a\u3051\u308b\u5272\u308a\u8fbc\u307f\u306e\u533a\u5225\u306e\u70ba\u306e\u6982\u5ff5\u3067\u3059\u306d\u3002<br \/>\n\u5b9f\u969b\u306f\u305f\u3060\u306e\u95a2\u6570\u306e\u914d\u5217\u306e\u3088\u3046\u306a\u3082\u306e\u3067\u3057\u305f\u3002<\/p>\n<p>\u500b\u5225\u306e\u7bc0\u306e\u7406\u89e3\u5ea6\u306f\u5c11\u3057\u3065\u3064\u4e0a\u304c\u3063\u3066\u304d\u3066\u308b\u6c17\u304c\u3057\u307e\u3059\u3002<br \/>\n\u305d\u308c\u305e\u308c\u306e\u95a2\u9023\u3084\u5168\u4f53\u306e\u4e2d\u3067\u3069\u3053\u306b\u4f4d\u7f6e\u3059\u308b\u306e\u304b\u304c\u30d4\u30f3\u3068\u6765\u308b\u3088\u3046\u306b\u306a\u308c\u3070\u3082\u3063\u3068\u7406\u89e3\u304c\u6df1\u307e\u308b\u3093\u3058\u3083\u306a\u3044\u304b\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[32],"tags":[405],"class_list":["post-1397","post","type-post","status-publish","format-standard","hentry","category-tech","tag-xv6"],"_links":{"self":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/posts\/1397","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/comments?post=1397"}],"version-history":[{"count":0,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/posts\/1397\/revisions"}],"wp:attachment":[{"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/media?parent=1397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/categories?post=1397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/peta.okechan.net\/blog\/wp-json\/wp\/v2\/tags?post=1397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}