plic__init
x86のLocal APICにあたるのか、IO APICに当たるのかはわかっていない
RISC-V privileged manual のsection 7に詳しくある. さきにそれを読んで概要を掴んだほうがよさそう
割り込みは2つのみ
コメントのPLICのメモリーマップがある
code:plic.c memory map
/*
* The PLIC consists of memory-mapped control registers, with a memory map as
* follows:
*
* base + 0x000000: Reserved (interrupt source 0 does not exist)
* base + 0x000004: Interrupt source 1 priority
* base + 0x000008: Interrupt source 2 priority
* ...
* base + 0x000FFC: Interrupt source 1023 priority
* base + 0x001000: Pending 0
* base + 0x001FFF: Pending
* base + 0x002000: Enable bits for sources 0-31 on context 0
* base + 0x002004: Enable bits for sources 32-63 on context 0
* ...
* base + 0x0020FC: Enable bits for sources 992-1023 on context 0
* base + 0x002080: Enable bits for sources 0-31 on context 1
* ...
* base + 0x002100: Enable bits for sources 0-31 on context 2
* ...
* base + 0x1F1F80: Enable bits for sources 992-1023 on context 15871
* base + 0x1F1F84: Reserved
* ... (higher context IDs would fit here, but wouldn't fit
* inside the per-context priority vector)
* base + 0x1FFFFC: Reserved
* base + 0x200000: Priority threshold for context 0
* base + 0x200004: Claim/complete for context 0
* base + 0x200008: Reserved
* ...
* base + 0x200FFC: Reserved
* base + 0x201000: Priority threshold for context 1
* base + 0x201004: Claim/complete for context 1
* ...
* base + 0xFFE000: Priority threshold for context 15871
* base + 0xFFE004: Claim/complete for context 15871
* base + 0xFFE008: Reserved
* ...
* base + 0xFFFFFC: Reserved
*/
code:riscv/plic.c
static int plic__init(struct kvm *kvm)
{
u32 i;
struct plic_context *c;
plic.kvm = kvm;
plic.dev_hdr = (struct device_header) {
.bus_type = DEVICE_BUS_MMIO,
.data = plic__generate_fdt_node,
};
plic.num_irq = MAX_DEVICES;
plic.num_irq_word = plic.num_irq / 32;
if ((plic.num_irq_word * 32) < plic.num_irq)
plic.num_irq_word++;
plic.max_prio = (1UL << PRIORITY_PER_ID) - 1;
plic.num_context = kvm->nrcpus * 2;
plic.contexts = calloc(plic.num_context, sizeof(struct plic_context));
if (!plic.contexts)
return -ENOMEM;
for (i = 0; i < plic.num_context; i++) {
c->s = &plic;
c->num = i;
c->vcpu = kvm->cpusi / 2; mutex_init(&c->irq_lock);
}
mutex_init(&plic.irq_lock);
kvm__register_mmio(kvm, RISCV_PLIC, RISCV_PLIC_SIZE,
false, plic__mmio_callback, &plic);
device__register(&plic.dev_hdr);
plic.ready = true;
return 0;
}