Skip to content

Commit e71c2f7

Browse files
josecmDavidMCerdeira
authored andcommitted
fix(riscv/aia): imsic offset depends on number of guest files
Previously the implementation assumed a single guest interrupt file per IMSIC. With this all interrupt files were contiguous in memory and the offset between each hart's interrupt files' base was two pages (s- and vs- level respectively). However, when the number of guest interrupt files is larger than 1, this is not true. This patch removes this assumption and calculates the size of each IMSIC memory address range (and therefore, offset between each hart's IMSIC base address) according to the layout mandated in the AIA spec version 1, which is dependent on GEILEN. Signed-off-by: Jose Martins <josemartins90@gmail.com>
1 parent 7e661fb commit e71c2f7

6 files changed

Lines changed: 16 additions & 6 deletions

File tree

scripts/arch/riscv/platform_defs_gen.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ void arch_platform_defs() {
1414

1515
if (IRQC == AIA) {
1616
printf("#define PLAT_IMSIC_MAX_INTERRUPTS %ld\n", platform.arch.irqc.aia.imsic.num_msis);
17+
18+
/**
19+
* This calculation follows the rules for the arrangement of memory regions for multiple
20+
* interrupt files defined in section 3.6 of "The RISC-V Advanced Interrupt Architecture"
21+
* version 1.0, with the smallest constant D as defined by the spec.
22+
*/
23+
size_t num_addr_bits = 0;
24+
while ((1UL << num_addr_bits) < (platform.arch.irqc.aia.imsic.num_guest_files + 1)) {
25+
num_addr_bits += 1;
26+
}
27+
printf("#define PLAT_IMSIC_HART_SIZE (%ld)\n", ((1UL << (num_addr_bits)) * PAGE_SIZE));
1728
}
1829

1930
}

src/arch/riscv/inc/arch/platform.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct arch_platform {
2525
struct {
2626
paddr_t base;
2727
size_t num_msis;
28+
size_t num_guest_files;
2829
} imsic;
2930
} aia;
3031
} irqc;

src/arch/riscv/irqc/aia/imsic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void imsic_init(void)
4545

4646
/** Map the interrupt files */
4747
imsic[cpu()->id] = (void*)mem_alloc_map_dev(&cpu()->as, SEC_HYP_GLOBAL, INVALID_VA,
48-
platform.arch.irqc.aia.imsic.base + (cpu()->id * PAGE_SIZE * IMSIC_NUM_FILES),
48+
platform.arch.irqc.aia.imsic.base + (cpu()->id * PLAT_IMSIC_HART_SIZE),
4949
NUM_PAGES(sizeof(struct imsic_global_hw)));
5050
}
5151

src/arch/riscv/irqc/aia/inc/imsic.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010
#include <platform.h>
1111

1212
#define IMSIC_MAX_INTERRUPTS (PLAT_IMSIC_MAX_INTERRUPTS)
13-
/** We only support 1 guest per hart at the moment */
14-
#define IMSIC_NUM_VS_FILES (1)
15-
#define IMSIC_NUM_FILES (IMSIC_NUM_VS_FILES + 1)
1613

1714
#define STOPEI_EEID (16)
1815

src/arch/riscv/irqc/aia/vimsic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ void vimsic_init(struct vm* vm, const union vm_irqc_dscrp* vm_irqc_dscrp)
2121

2222
imsic_vaddr = vm_irqc_dscrp->aia.imsic.base + (PAGE_SIZE * vcpu_id);
2323

24-
imsic_paddr = platform.arch.irqc.aia.imsic.base +
25-
(PAGE_SIZE * ((IMSIC_NUM_FILES * pcpu_id) + VS_FILE_IDX));
24+
imsic_paddr = platform.arch.irqc.aia.imsic.base + (PLAT_IMSIC_HART_SIZE * pcpu_id) +
25+
(PAGE_SIZE * VS_FILE_IDX);
2626

2727
if (imsic_vaddr != INVALID_VA) {
2828
mem_alloc_map_dev(&vm->as, SEC_VM_ANY, imsic_vaddr, imsic_paddr, 1);

src/platform/qemu-riscv64-virt/virt_desc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ struct platform platform = {
3535
.irqc.aia.aplic.base = 0xd000000,
3636
.irqc.aia.imsic.base = 0x28000000,
3737
.irqc.aia.imsic.num_msis = 255,
38+
.irqc.aia.imsic.num_guest_files = 1,
3839
#endif
3940

4041
#if (IPIC == IPIC_ACLINT)

0 commit comments

Comments
 (0)