xref: /openbmc/qemu/target/i386/hvf/x86_descr.c (revision e692f9c6a681de1372a41999b14a947a553b6a1a)
169e0a03cSPaolo Bonzini /*
269e0a03cSPaolo Bonzini  * Copyright (C) 2016 Veertu Inc,
369e0a03cSPaolo Bonzini  * Copyright (C) 2017 Google Inc,
469e0a03cSPaolo Bonzini  *
569e0a03cSPaolo Bonzini  * This program is free software; you can redistribute it and/or
669e0a03cSPaolo Bonzini  * modify it under the terms of the GNU Lesser General Public
769e0a03cSPaolo Bonzini  * License as published by the Free Software Foundation; either
88af82b8eSChetan Pant  * version 2.1 of the License, or (at your option) any later version.
969e0a03cSPaolo Bonzini  *
1069e0a03cSPaolo Bonzini  * This program is distributed in the hope that it will be useful,
1169e0a03cSPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1269e0a03cSPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1369e0a03cSPaolo Bonzini  * Lesser General Public License for more details.
1469e0a03cSPaolo Bonzini  *
1569e0a03cSPaolo Bonzini  * You should have received a copy of the GNU Lesser General Public
1669e0a03cSPaolo Bonzini  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
1769e0a03cSPaolo Bonzini  */
1869e0a03cSPaolo Bonzini 
1969e0a03cSPaolo Bonzini #include "qemu/osdep.h"
2069e0a03cSPaolo Bonzini 
2169e0a03cSPaolo Bonzini #include "vmx.h"
2269e0a03cSPaolo Bonzini #include "x86_descr.h"
2369e0a03cSPaolo Bonzini 
2469e0a03cSPaolo Bonzini #define VMX_SEGMENT_FIELD(seg)                        \
256701d81dSPaolo Bonzini     [R_##seg] = {                                     \
2669e0a03cSPaolo Bonzini         .selector = VMCS_GUEST_##seg##_SELECTOR,      \
2769e0a03cSPaolo Bonzini         .base = VMCS_GUEST_##seg##_BASE,              \
2869e0a03cSPaolo Bonzini         .limit = VMCS_GUEST_##seg##_LIMIT,            \
2969e0a03cSPaolo Bonzini         .ar_bytes = VMCS_GUEST_##seg##_ACCESS_RIGHTS, \
3069e0a03cSPaolo Bonzini }
3169e0a03cSPaolo Bonzini 
3269e0a03cSPaolo Bonzini static const struct vmx_segment_field {
3369e0a03cSPaolo Bonzini     int selector;
3469e0a03cSPaolo Bonzini     int base;
3569e0a03cSPaolo Bonzini     int limit;
3669e0a03cSPaolo Bonzini     int ar_bytes;
3769e0a03cSPaolo Bonzini } vmx_segment_fields[] = {
3869e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(ES),
3969e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(CS),
4069e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(SS),
4169e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(DS),
4269e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(FS),
4369e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(GS),
4469e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(LDTR),
4569e0a03cSPaolo Bonzini     VMX_SEGMENT_FIELD(TR),
4669e0a03cSPaolo Bonzini };
4769e0a03cSPaolo Bonzini 
vmx_read_segment_limit(CPUState * cpu,X86Seg seg)486701d81dSPaolo Bonzini uint32_t vmx_read_segment_limit(CPUState *cpu, X86Seg seg)
4969e0a03cSPaolo Bonzini {
503b295bcbSPhilippe Mathieu-Daudé     return (uint32_t)rvmcs(cpu->accel->fd, vmx_segment_fields[seg].limit);
5169e0a03cSPaolo Bonzini }
5269e0a03cSPaolo Bonzini 
vmx_read_segment_ar(CPUState * cpu,X86Seg seg)536701d81dSPaolo Bonzini uint32_t vmx_read_segment_ar(CPUState *cpu, X86Seg seg)
5469e0a03cSPaolo Bonzini {
553b295bcbSPhilippe Mathieu-Daudé     return (uint32_t)rvmcs(cpu->accel->fd, vmx_segment_fields[seg].ar_bytes);
5669e0a03cSPaolo Bonzini }
5769e0a03cSPaolo Bonzini 
vmx_read_segment_base(CPUState * cpu,X86Seg seg)586701d81dSPaolo Bonzini uint64_t vmx_read_segment_base(CPUState *cpu, X86Seg seg)
5969e0a03cSPaolo Bonzini {
603b295bcbSPhilippe Mathieu-Daudé     return rvmcs(cpu->accel->fd, vmx_segment_fields[seg].base);
6169e0a03cSPaolo Bonzini }
6269e0a03cSPaolo Bonzini 
vmx_read_segment_selector(CPUState * cpu,X86Seg seg)636701d81dSPaolo Bonzini x68_segment_selector vmx_read_segment_selector(CPUState *cpu, X86Seg seg)
6469e0a03cSPaolo Bonzini {
6569e0a03cSPaolo Bonzini     x68_segment_selector sel;
663b295bcbSPhilippe Mathieu-Daudé     sel.sel = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].selector);
6769e0a03cSPaolo Bonzini     return sel;
6869e0a03cSPaolo Bonzini }
6969e0a03cSPaolo Bonzini 
vmx_write_segment_selector(CPUState * cpu,x68_segment_selector selector,X86Seg seg)70*f8436a16SPhilippe Mathieu-Daudé void vmx_write_segment_selector(CPUState *cpu, x68_segment_selector selector, X86Seg seg)
7169e0a03cSPaolo Bonzini {
723b295bcbSPhilippe Mathieu-Daudé     wvmcs(cpu->accel->fd, vmx_segment_fields[seg].selector, selector.sel);
7369e0a03cSPaolo Bonzini }
7469e0a03cSPaolo Bonzini 
vmx_read_segment_descriptor(CPUState * cpu,struct vmx_segment * desc,X86Seg seg)75*f8436a16SPhilippe Mathieu-Daudé void vmx_read_segment_descriptor(CPUState *cpu, struct vmx_segment *desc, X86Seg seg)
7669e0a03cSPaolo Bonzini {
773b295bcbSPhilippe Mathieu-Daudé     desc->sel = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].selector);
783b295bcbSPhilippe Mathieu-Daudé     desc->base = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].base);
793b295bcbSPhilippe Mathieu-Daudé     desc->limit = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].limit);
803b295bcbSPhilippe Mathieu-Daudé     desc->ar = rvmcs(cpu->accel->fd, vmx_segment_fields[seg].ar_bytes);
8169e0a03cSPaolo Bonzini }
8269e0a03cSPaolo Bonzini 
vmx_write_segment_descriptor(CPUState * cpu,struct vmx_segment * desc,X86Seg seg)836701d81dSPaolo Bonzini void vmx_write_segment_descriptor(CPUState *cpu, struct vmx_segment *desc, X86Seg seg)
8469e0a03cSPaolo Bonzini {
8569e0a03cSPaolo Bonzini     const struct vmx_segment_field *sf = &vmx_segment_fields[seg];
8669e0a03cSPaolo Bonzini 
873b295bcbSPhilippe Mathieu-Daudé     wvmcs(cpu->accel->fd, sf->base, desc->base);
883b295bcbSPhilippe Mathieu-Daudé     wvmcs(cpu->accel->fd, sf->limit, desc->limit);
893b295bcbSPhilippe Mathieu-Daudé     wvmcs(cpu->accel->fd, sf->selector, desc->sel);
903b295bcbSPhilippe Mathieu-Daudé     wvmcs(cpu->accel->fd, sf->ar_bytes, desc->ar);
9169e0a03cSPaolo Bonzini }
9269e0a03cSPaolo Bonzini 
x86_segment_descriptor_to_vmx(CPUState * cpu,x68_segment_selector selector,struct x86_segment_descriptor * desc,struct vmx_segment * vmx_desc)93*f8436a16SPhilippe Mathieu-Daudé void x86_segment_descriptor_to_vmx(CPUState *cpu, x68_segment_selector selector,
94*f8436a16SPhilippe Mathieu-Daudé                                    struct x86_segment_descriptor *desc,
95*f8436a16SPhilippe Mathieu-Daudé                                    struct vmx_segment *vmx_desc)
9669e0a03cSPaolo Bonzini {
9769e0a03cSPaolo Bonzini     vmx_desc->sel = selector.sel;
9869e0a03cSPaolo Bonzini     vmx_desc->base = x86_segment_base(desc);
9969e0a03cSPaolo Bonzini     vmx_desc->limit = x86_segment_limit(desc);
10069e0a03cSPaolo Bonzini 
10169e0a03cSPaolo Bonzini     vmx_desc->ar = (selector.sel ? 0 : 1) << 16 |
10269e0a03cSPaolo Bonzini                     desc->g << 15 |
10369e0a03cSPaolo Bonzini                     desc->db << 14 |
10469e0a03cSPaolo Bonzini                     desc->l << 13 |
10569e0a03cSPaolo Bonzini                     desc->avl << 12 |
10669e0a03cSPaolo Bonzini                     desc->p << 7 |
10769e0a03cSPaolo Bonzini                     desc->dpl << 5 |
10869e0a03cSPaolo Bonzini                     desc->s << 4 |
10969e0a03cSPaolo Bonzini                     desc->type;
11069e0a03cSPaolo Bonzini }
11169e0a03cSPaolo Bonzini 
vmx_segment_to_x86_descriptor(CPUState * cpu,struct vmx_segment * vmx_desc,struct x86_segment_descriptor * desc)112*f8436a16SPhilippe Mathieu-Daudé void vmx_segment_to_x86_descriptor(CPUState *cpu, struct vmx_segment *vmx_desc,
113*f8436a16SPhilippe Mathieu-Daudé                                    struct x86_segment_descriptor *desc)
11469e0a03cSPaolo Bonzini {
11569e0a03cSPaolo Bonzini     x86_set_segment_limit(desc, vmx_desc->limit);
11669e0a03cSPaolo Bonzini     x86_set_segment_base(desc, vmx_desc->base);
11769e0a03cSPaolo Bonzini 
11869e0a03cSPaolo Bonzini     desc->type = vmx_desc->ar & 15;
11969e0a03cSPaolo Bonzini     desc->s = (vmx_desc->ar >> 4) & 1;
12069e0a03cSPaolo Bonzini     desc->dpl = (vmx_desc->ar >> 5) & 3;
12169e0a03cSPaolo Bonzini     desc->p = (vmx_desc->ar >> 7) & 1;
12269e0a03cSPaolo Bonzini     desc->avl = (vmx_desc->ar >> 12) & 1;
12369e0a03cSPaolo Bonzini     desc->l = (vmx_desc->ar >> 13) & 1;
12469e0a03cSPaolo Bonzini     desc->db = (vmx_desc->ar >> 14) & 1;
12569e0a03cSPaolo Bonzini     desc->g = (vmx_desc->ar >> 15) & 1;
12669e0a03cSPaolo Bonzini }
12769e0a03cSPaolo Bonzini 
128