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");