irq: size _irq_to_interrupt_vector_table
Most systems have far less than 256 IRQ lines available, so
save some bytes in ROM by making this a config option.
On systems with MVIC, omit the table entirely as the mapping
is fixed.
The build cmd_gen_idt is slightly easier to read and will fail
immediately if any of the commands in the sequence error out.
Change-Id: I411f114557591e5cd96b618e6f79f97e8bedadf0
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
diff --git a/Makefile b/Makefile
index ba6e363..c94854d 100644
--- a/Makefile
+++ b/Makefile
@@ -769,19 +769,21 @@
$(Q)$(LD) -T linker.cmd @$(KERNEL_NAME).lnk -o $@
quiet_cmd_gen_idt = SIDT $@
- cmd_gen_idt = \
-( \
- $(OBJCOPY) -I $(OUTPUT_FORMAT) -O binary -j intList $< isrList.bin; \
- $(GENIDT) -i isrList.bin -n $(CONFIG_IDT_NUM_VECTORS) -o staticIdt.bin \
- -b int_vector_alloc.bin -m irq_int_vector_map.bin; \
- $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
- --rename-section .data=staticIdt staticIdt.bin staticIdt.o; \
- $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
- --rename-section .data=int_vector_alloc int_vector_alloc.bin int_vector_alloc.o;\
- $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
- --rename-section .data=irq_int_vector_map irq_int_vector_map.bin \
- irq_int_vector_map.o; \
- rm staticIdt.bin irq_int_vector_map.bin int_vector_alloc.bin isrList.bin \
+ cmd_gen_idt = \
+( \
+ $(OBJCOPY) -I $(OUTPUT_FORMAT) -O binary -j intList $< isrList.bin && \
+ $(GENIDT) -i isrList.bin -n $(CONFIG_IDT_NUM_VECTORS) -o staticIdt.bin \
+ -b int_vector_alloc.bin -m irq_int_vector_map.bin \
+ -l $(CONFIG_MAX_IRQ_LINES) && \
+ $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
+ --rename-section .data=staticIdt staticIdt.bin staticIdt.o && \
+ $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
+ --rename-section .data=int_vector_alloc int_vector_alloc.bin \
+ int_vector_alloc.o && \
+ $(OBJCOPY) -I binary -B $(OUTPUT_ARCH) -O $(OUTPUT_FORMAT) \
+ --rename-section .data=irq_int_vector_map irq_int_vector_map.bin \
+ irq_int_vector_map.o && \
+ rm staticIdt.bin irq_int_vector_map.bin int_vector_alloc.bin isrList.bin\
)
staticIdt.o: $(TMP_ELF)
diff --git a/arch/x86/core/Kconfig b/arch/x86/core/Kconfig
index 70713c1..2907aa4 100644
--- a/arch/x86/core/Kconfig
+++ b/arch/x86/core/Kconfig
@@ -48,6 +48,18 @@
Interrupt Descriptor Table (IDT). By default all 256 vectors are
supported in an IDT requiring 2048 bytes of memory.
+config MAX_IRQ_LINES
+ int
+ prompt "Number of IRQ lines"
+ default 128
+ range 0 256
+ help
+ This option specifies the number of IRQ lines in the system.
+ It can be tuned to save some bytes in ROM, as it determines the
+ size of the _irq_to_interrupt_vector_table, which is used at runtime
+ to program to the PIC the association between vectors and
+ interrupts.
+
config PHYS_LOAD_ADDR
hex "Physical load address"
# Default value must be supplied by platform
diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h
index 4ead9c8..da5e195 100644
--- a/include/arch/x86/arch.h
+++ b/include/arch/x86/arch.h
@@ -274,14 +274,21 @@
_IRQ_TO_INTERRUPT_VECTOR(irq_p); \
})
-extern unsigned char _irq_to_interrupt_vector[];
+#ifdef CONFIG_MVIC
+/* Fixed vector-to-irq association mapping.
+ * No need for the table at all.
+ */
+#define _IRQ_TO_INTERRUPT_VECTOR(irq) (irq + 0x20)
+#else
/**
* @brief Convert a statically connected IRQ to its interrupt vector number
*
* @param irq IRQ number
*/
+extern unsigned char _irq_to_interrupt_vector[];
#define _IRQ_TO_INTERRUPT_VECTOR(irq) \
((unsigned int) _irq_to_interrupt_vector[irq])
+#endif
/**
diff --git a/include/arch/x86/linker-common-sections.h b/include/arch/x86/linker-common-sections.h
index 3a0cace..91a751a 100644
--- a/include/arch/x86/linker-common-sections.h
+++ b/include/arch/x86/linker-common-sections.h
@@ -127,7 +127,9 @@
#if ALL_DYN_STUBS == 0
IDT_MEMORY
#endif
+#ifndef CONFIG_MVIC
IRQ_TO_INTERRUPT_VECTOR_MEMORY
+#endif
KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE)
} GROUP_LINK_IN(ROMABLE_REGION)
diff --git a/include/arch/x86/linker-defs-arch.h b/include/arch/x86/linker-defs-arch.h
index 9ebb114..0162cc0 100644
--- a/include/arch/x86/linker-defs-arch.h
+++ b/include/arch/x86/linker-defs-arch.h
@@ -50,9 +50,8 @@
#define INTERRUPT_VECTORS_ALLOCATED . += ((CONFIG_IDT_NUM_VECTORS + 31) / 32);
/*
* Both IRQs and interrupt vectors may be in the range of 0..255 inclusive.
- * Save 256 bytes for the IRQ to interrupt vector mapping.
*/
- #define IRQ_TO_INTERRUPT_VECTOR . += 256;
+ #define IRQ_TO_INTERRUPT_VECTOR . += CONFIG_MAX_IRQ_LINES;
#endif
/*
diff --git a/scripts/gen_idt/gen_idt.c b/scripts/gen_idt/gen_idt.c
index 9294c81..11037b7 100644
--- a/scripts/gen_idt/gen_idt.c
+++ b/scripts/gen_idt/gen_idt.c
@@ -117,6 +117,7 @@
static char *filenames[NFILES];
static unsigned int num_vectors = (unsigned int)-1;
static struct version version = {KERNEL_VERSION, 1, 1, 6};
+static unsigned int num_irq_lines = -1;
int main(int argc, char *argv[])
{
@@ -136,7 +137,7 @@
char *endptr;
int ii, opt;
- while ((opt = getopt(argc, argv, "hb:i:o:m:n:v")) != -1) {
+ while ((opt = getopt(argc, argv, "hb:i:o:m:n:vl:")) != -1) {
switch (opt) {
case 'b':
filenames[BFILE] = optarg;
@@ -153,6 +154,13 @@
case 'h':
usage(LONG_USAGE);
exit(0);
+ case 'l':
+ num_irq_lines = (unsigned int) strtoul(optarg, &endptr, 10);
+ if ((*optarg == '\0') || (*endptr != '\0')) {
+ usage(SHORT_USAGE);
+ exit(-1);
+ }
+ break;
case 'n':
num_vectors = (unsigned int) strtoul(optarg, &endptr, 10);
if ((*optarg == '\0') || (*endptr != '\0')) {
@@ -174,6 +182,11 @@
exit(-1);
}
+ if (num_irq_lines > MAX_IRQS) {
+ usage(SHORT_USAGE);
+ exit(-1);
+ }
+
for (ii = IFILE; ii < NUSERFILES; ii++) {
if (!filenames[ii]) {
usage(SHORT_USAGE);
@@ -418,20 +431,20 @@
continue;
}
- if (supplied_entry[i].irq >= MAX_IRQS) {
+ if (supplied_entry[i].irq >= num_irq_lines) {
/*
* If code to support the PIC is re-introduced, then this
* check will need to be updated.
*/
fprintf(stderr, "IRQ must be between 0 and %d inclusive.\n",
- MAX_IRQS - 1);
+ num_irq_lines - 1);
show_entry(&supplied_entry[i]);
clean_exit(-1);
}
num_irqs[i]++;
}
- for (i = 0; i < MAX_IRQS; i++) {
+ for (i = 0; i < num_irq_lines; i++) {
if (num_irqs[i] > 1) {
fprintf(stderr, "Multiple requests for IRQ %d detected.\n", i);
clean_exit(-1);
@@ -600,7 +613,7 @@
clean_exit(-1);
}
- bytes_to_write = sizeof(map_irq_to_vector_id);
+ bytes_to_write = num_irq_lines;
bytes_written = write(fds[MFILE], map_irq_to_vector_id, bytes_to_write);
if (bytes_written != bytes_to_write) {
fprintf(stderr, "Failed to write all data to '%s'.\n",
@@ -646,6 +659,8 @@
" [Mandatory] The IRQ to interrupt vector output file\n\n"
" -n <n>\n\n"
" [Mandatory] Number of vectors\n\n"
+ " -l <n>\n\n"
+ " [Mandatory] Number of IRQ lines\n\n"
" -v Display version.\n\n"
" -h Display this help.\n\n"
"\nReturns -1 on error, 0 on success\n\n");