[svsm-devel] [EXTERNAL] Extended Interrupt Information

Melody (Huibo) Wang huibo.wang at amd.com
Wed May 7 22:43:45 CEST 2025


Hi Jon,

I am updating the GHCB spec with Alternate Injection info. 

Regarding this paragraph in the AI spec: "To indicate separate interrupt sources for each VMPL, the #HV doorbell page is further extended to define the first 256 bytes. Bytes 0-31 contain interrupt information associated with VMPL0 itself." 

So this is 256 bytes in total (!) and the first 4 bytes - PendingEvent and
InjectionInfo - are included in those 256 bytes, correct?

The layout is NOT PendingEvent, InjectionInfo, 256 more bytes for a total of 260 bytes, right?

IOW, the first 4 bytes are part of the SVSM interrupt information, which is how I did it in my test program.

Sorry but I would like to absolutely make sure this is crystal clear in the GHCB spec so that there are no ambiguities.

Thanks a lot!

Melody



On 5/5/2025 3:31 PM, Melody (Huibo) Wang wrote:
> Thanks for confirming, it helps. :)
> 
> Thanks,
> Melody
> 
> On 5/5/2025 3:19 PM, Jon Lange wrote:
>> I believe your definitions are correct.
>>
>> -Jon
>>
>> -----Original Message-----
>> From: Melody (Huibo) Wang <huibo.wang at amd.com> 
>> Sent: Sunday, May 4, 2025 1:28 PM
>> To: Jon Lange <jlange at microsoft.com>
>> Cc: Lendacky, Thomas <Thomas.Lendacky at amd.com>; Jörg Rödel <joro at 8bytes.org>; svsm-devel at coconut-svsm.dev
>> Subject: [EXTERNAL] Extended Interrupt Information
>>
>> Hi Jon,
>>
>> I have written a small C program that implements the new #HV doorbell page with extended interrupt information. 
>>
>> Could you please confirm that my reading of the spec is correct, especially fields layout and order? 
>>
>> #include <errno.h>
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <string.h>
>> #include <assert.h>
>>
>> #define PAGE_SIZE		4096
>>
>> #define DIV_ROUND_UP(n,d)	(((n) + (d) - 1) / (d))
>>
>> #define BITS_PER_TYPE(type)	(sizeof(type) * 8)
>> #define BITS_TO_LONGS(nr)	DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
>>
>> #define DECLARE_BITMAP(name,bits) \
>> 	unsigned long name[BITS_TO_LONGS(bits)]
>>
>> typedef unsigned char u8;
>> typedef unsigned short u16;
>>
>> /*
>>  * Hypervisor doorbell page:
>>  *
>>  * Used when restricted injection is enabled for a VM. One page in size that
>>  * is shared between the guest and hypervisor to communicate exception and
>>  * interrupt events.
>>  */
>> struct ext_irq_desc {
>> 	/* first 16-bit word */
>> 	struct {
>> 		u16 si_vector:		8,
>> 		    nmi:		1,
>> 		    mce:		1,
>> 		    trigger_mode:	1,
>> 		    reserved1:		3,
>> 		    multi_interrupts:	1,
>> 		    reserved2:		1;
>> 	} word0;
>>
>> 	/* Second 16-bit word */
>> 	struct {
>> 		u16 reserved5:		15,
>> 		    interrupt_vector:	1;
>> 	} word1;
>>
>> 	/*
>> 	 * Set the corresponding vmpl?_irq bit in inj_info after setting
>> 	 * multiple bits here.
>> 	 */
>>         u16 interrupt_bit_vector[14];
>>
>> 	/*
>> 	 * Reserved for future use.
>> 	 * TODO: Code should check them and fail if set.
>> 	 */
>>         u8 reserved6[32];
>> } __attribute__((packed));
>>
>> struct hvdb {
>> 	/* first 16-bit word PendingEvent */
>> 	struct {
>> 		/* Non-maskable event indicators */
>> 		u16 reserved1:          8,
>> 		nmi:                    1,
>> 		mce:                    1,
>> 		reserved2:              5,
>> 		no_further_signal:      1;
>> 	} pending_event;
>>
>> 	/* Second 16-bit word InjectionInfo */
>> 	union {
>> 		struct {
>> 			u16 no_eoi_required:	1,
>> 			    reserved3:		7,
>> 			    vmpl1_irq:		1,
>> 			    vmpl2_irq:		1,
>> 			    vmpl3_irq:		1,
>> 			    reserved4:		4;
>> 		} inj_info;
>> 		u16 injection_info;
>> 	};
>>
>> 	/* IRQ info associated with the SVSM itself */
>> 	/* XXX: code should enforce bytes [32-63] are zero */
>> 	u8 svsm_irq_info[64 - 4];
>>
>> 	/* VMPL[1-3] extended IRQ descriptors */
>>         struct ext_irq_desc irqs[3];
>>
>>         /* Remainder of the page is for software use */
>>         u8 reserved[PAGE_SIZE - 256];
>> } __attribute__((packed));
>>
>> int main(void)
>> {
>> 	struct hvdb h = { };
>>
>> 	assert(sizeof(struct ext_irq_desc) == 64);
>>
>> 	printf("sizeof(struct ext_irq_desc): %zu\n", sizeof(struct ext_irq_desc));
>>
>> 	h.inj_info.no_eoi_required = 1;
>> 	h.inj_info.vmpl3_irq = 1;
>>
>> 	printf("injection_info: 0x%x\n", h.injection_info);
>>
>> 	return 0;
>> }
>>
>>
>> Thanks,
>> Melody
> 



More information about the Svsm-devel mailing list