Commit c4780c3c authored by Charlie Jacobsen's avatar Charlie Jacobsen Committed by Vikram Narayanan

Segment and desc table regs, address space layout in place (untested).

Address space layout includes tss, gdt, ipc registers, and small
stack. See lcd-domains-arch.h.
-- a tss may be required (not sure) while running in non-root,
   even though a stack switch does not occur
-- a gdt may also be required (even though all info is written in
   the hidden part of the segment registers); again, not sure

4 KBs is reserved for an IDT if it is needed (not mapped or
allocated).

GDT layout given in lcd-domains-arch.h. (GDT build code to
be implemented / copied over next.)

LDT is not used (so no need to load access rights, etc.). It
is marked as unusable.

Fixed segment register limit fields. These must be 32 bits and
are always byte granularity. The granularity field in the
access rights bits is confusing (see Intel SDM V3 26.3.1.2).
parent c9cb61a2
......@@ -36,10 +36,6 @@ enum lcd_arch_reg {
LCD_ARCH_NUM_REGS
};
#define LCD_ARCH_CS_SELECTOR 1
#define LCD_ARCH_FS_SELECTOR 2
#define LCD_ARCH_GS_SELECTOR 3
#define LCD_ARCH_EPT_WALK_LENGTH 4
#define LCD_ARCH_EPTP_WALK_SHIFT 3
#define LCD_ARCH_PTRS_PER_EPTE (1 << 9)
......@@ -53,6 +49,22 @@ struct lcd_arch_ept {
typedef epte_t lcd_arch_epte_t;
struct lcd_arch_tss {
/*
* Intel SDM V3 7.7
*
* Base TSS before I/O bitmap, etc.
*/
struct x86_hw_tss base_tss;
/*
* I/O bitmap must be at least 8 bits to contain
* required 8 bits that are set.
*
* Intel SDM V1 16.5.2
*/
u8 io_bitmap[1];
} __attribute__((packed));
struct lcd_arch {
/*
......@@ -70,8 +82,10 @@ struct lcd_arch {
int launched;
int vpid;
struct lcd_arch_vmcs *vmcs;
struct lcd_arch_ept ept;
struct desc_struct *gdt;
struct desc_struct *gdt;
struct lcd_arch_tss *tss;
u8 fail;
u64 exit_reason;
......@@ -157,5 +171,67 @@ int lcd_arch_ept_set(lcd_arch_epte_t *epte, u64 hpa);
*/
u64 lcd_arch_ept_hpa(lcd_arch_epte_t *epte);
/*
* GDT Layout
* ==========
* 0 = NULL
* 1 = Code segment
* 2 = Data segment
* 3 = Data segment
* 4 = Task segment
*
* See Intel SDM V3 26.3.1.2, 26.3.1.3 for register requirements.
* See Intel SDM V3 3.4.2, 3.4.3 for segment register layout
* See Intel SDM V3 2.4.1 - 2.4.4 for gdtr, ldtr, idtr, tr
*/
#define LCD_ARCH_FS_BASE 0x0UL
#define LCD_ARCH_FS_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GS_BASE 0x0UL
#define LCD_ARCH_GS_LIMIT 0xFFFFFFFF
#define LCD_ARCH_GDTR_BASE 0x0000000000002000UL
#define LCD_ARCH_GDTR_LIMIT ~(PAGE_SIZE - 1)
#define LCD_ARCH_TSS_BASE 0x0000000000003000UL
/* tss base + limit = address of last byte in tss, hence -1 */
#define LCD_ARCH_TSS_LIMIT (sizeof(struct lcd_arch_tss) - 1)
#define LCD_ARCH_IDTR_BASE 0x0UL
#define LCD_ARCH_IDTR_LIMIT 0x0 /* no idt right now */
#define LCD_ARCH_CS_SELECTOR (1 << 3)
#define LCD_ARCH_FS_SELECTOR (2 << 3)
#define LCD_ARCH_GS_SELECTOR (3 << 3)
#define LCD_ARCH_TR_SELECTOR (4 << 3) /* TI must be 0 */
#define LCD_ARCH_LDTR_SELECTOR (0 << 3) /* unusable */
/*
* Guest Physical Memory Layout
* ============================
*
* +---------------------------+ 0xFFFF FFFF FFFF FFFF
* | |
* : :
* : Free / Unmapped :
* : :
* | |
* LCD_ARCH_STACK_TOP,---> +---------------------------+ 0x0000 0000 0000 4000
* LCD_ARCH_FREE | |
* | Stack |
* : (grows down) : (4 KBs)
* : :
* | |
* | IPC Message Registers |
* LCD_ARCH_IPC_REGS-----> +---------------------------+ 0x0000 0000 0000 3000
* | TSS |
* | only sizeof(tss) is | (4 KBs)
* | used |
* LCD_ARCH_TSS_BASE-----> +---------------------------+ 0x0000 0000 0000 2000
* | GDT | (4 KBs)
* LCD_ARCH_GDT_BASE-----> +---------------------------+ 0x0000 0000 0000 1000
* | Reserved |
* | (not mapped) | (4 KBs)
* +---------------------------+ 0x0000 0000 0000 0000
*/
#define LCD_ARCH_IPC_REGS 0x0000000000003000UL
#define LCD_ARCH_STACK_TOP 0x0000000000004000UL
#define LCD_ARCH_FREE LCD_ARCH_STACK_TOP
#endif /* LCD_DOMAINS_ARCH_H */
......@@ -1294,8 +1294,6 @@ static void vmx_setup_vmcs_guest_regs(struct lcd_arch *vcpu)
vmcs_writel(GUEST_IA32_EFER, EFER_LME | EFER_LMA);
/*
* gdtr -- to be set when guest address space set up
*
* %rip, %rsp -- to be set when guest address space set up
*/
......@@ -1306,56 +1304,76 @@ static void vmx_setup_vmcs_guest_regs(struct lcd_arch *vcpu)
*/
vmcs_writel(GUEST_RFLAGS, 0x02);
/*
* Guest segment bases
/*
*===--- Segment and descriptor table registers ---===
*
* -- Use same %fs and %gs as host
* See Intel SDM V3 26.3.1.2, 26.3.1.3 for register requirements
*/
/*
* Bases
*/
vmcs_writel(GUEST_CS_BASE, 0);
vmcs_writel(GUEST_DS_BASE, 0);
vmcs_writel(GUEST_ES_BASE, 0);
vmcs_writel(GUEST_SS_BASE, 0);
rdmsrl(MSR_GS_BASE, tmpl);
vmcs_writel(GUEST_GS_BASE, tmpl);
rdmsrl(MSR_FS_BASE, tmpl);
vmcs_writel(GUEST_FS_BASE, tmpl);
vmcs_writel(GUEST_FS_BASE, LCD_ARCH_FS_BASE);
vmcs_writel(GUEST_GS_BASE, LCD_ARCH_GS_BASE);
vmcs_writel(GUEST_GDTR_BASE, LCD_ARCH_GDTR_BASE);
vmcs_writel(GUEST_IDTR_BASE, LCD_ARCH_IDTR_BASE);
vmcs_writel(GUEST_TR_BASE, LCD_ARCH_TSS_BASE);
/*
* Guest segment access rights
* Access rights
*
* -- %cs:
* -- code segment type, execute/read/accessed
* -- code or data segment desc type
* -- dpl = 0
* -- present
* -- 64-bit mode
* -- 4KB granularity
* -- granularity = 1
* -- %ds, %es, %fs, %gs, %ss
* -- data segment type, read/write/accessed
* -- code or data segment desc type
* -- dpl = 0
* -- present
* -- 4KB granularity
* -- granularity = 1
* -- ldtr
* -- unusable (bit 16 = 1)
* -- tr
* -- 64-bit busy tss
* -- present
* -- granularity = 0
*
* Intel SDM V3 24.4.1, 3.4.5
* Intel SDM V3 24.4.1, 3.4.5, 26.3.1.2
*/
vmcs_writel(GUEST_CS_AR_BYTES, 0xA09B);
vmcs_writel(GUEST_DS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_ES_AR_BYTES, 0x8093);
vmcs_writel(GUEST_FS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_GS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_SS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_CS_AR_BYTES, 0xA09B);
vmcs_writel(GUEST_DS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_ES_AR_BYTES, 0x8093);
vmcs_writel(GUEST_FS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_GS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_SS_AR_BYTES, 0x8093);
vmcs_writel(GUEST_LDTR_AR_BYTES, (1 << 16));
vmcs_writel(GUEST_TR_AR_BYTES, 0x0083);
/*
* Guest segment limits
* Limits
*
* Granularity = 1, so units are in 4KBs (not bytes) and
* hence each is a 4GB limit.
*/
vmcs_write32(GUEST_CS_LIMIT, 0xFFFFF);
vmcs_write32(GUEST_DS_LIMIT, 0xFFFFF);
vmcs_write32(GUEST_ES_LIMIT, 0xFFFFF);
vmcs_write32(GUEST_FS_LIMIT, 0xFFFFF);
vmcs_write32(GUEST_GS_LIMIT, 0xFFFFF);
vmcs_write32(GUEST_SS_LIMIT, 0xFFFFF);
* -- Limits are always in bytes
* -- Granularity (see above) seems to have different
* semantics? See Intel SDM V3 26.3.1.2.
* -- For gdtr and idtr, upper 16 bits are set to 0 on vm enter.
*/
vmcs_write32(GUEST_CS_LIMIT, 0xFFFFFFFF);
vmcs_write32(GUEST_DS_LIMIT, 0xFFFFFFFF);
vmcs_write32(GUEST_ES_LIMIT, 0xFFFFFFFF);
vmcs_write32(GUEST_FS_LIMIT, 0xFFFFFFFF);
vmcs_write32(GUEST_GS_LIMIT, 0xFFFFFFFF);
vmcs_write32(GUEST_SS_LIMIT, 0xFFFFFFFF);
vmcs_write32(GUEST_TR_LIMIT, LCD_ARCH_TSS_LIMIT);
vmcs_write32(GUEST_GDTR_LIMIT, LCD_ARCH_GDTR_LIMIT);
vmcs_write32(GUEST_IDTR_LIMIT, LCD_ARCH_IDTR_LIMIT);
/*
* Guest segment selectors
......@@ -1370,6 +1388,7 @@ static void vmx_setup_vmcs_guest_regs(struct lcd_arch *vcpu)
vmcs_write16(GUEST_FS_SELECTOR, LCD_ARCH_FS_SELECTOR); /* data */
vmcs_write16(GUEST_GS_SELECTOR, LCD_ARCH_GS_SELECTOR); /* data */
vmcs_write16(GUEST_SS_SELECTOR, 0); /* ignored */
vmcs_write16(GUEST_TR_SELECTOR, LCD_ARCH_TR_SELECTOR);
/*
* Guest activity state = active
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment