Signed-off-by: Kevin O'Connor kevin@koconnor.net --- Makefile | 2 +- src/bregs.h | 22 +------ src/fw/acpi.c | 1 + src/fw/mptable.c | 1 + src/fw/mtrr.c | 1 + src/fw/paravirt.c | 1 + src/fw/shadow.c | 1 + src/fw/smbios.c | 1 + src/fw/smm.c | 3 +- src/fw/smp.c | 1 + src/fw/xen.c | 1 + src/hw/pci.c | 1 + src/hw/timer.c | 1 + src/hw/usb-ehci.c | 1 + src/hw/usb-ohci.c | 1 + src/hw/usb.c | 1 + src/pmm.c | 1 + src/romlayout.S | 2 +- src/util.c | 16 ------ src/util.h | 141 --------------------------------------------- src/x86.c | 23 ++++++++ src/x86.h | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 22 files changed, 212 insertions(+), 179 deletions(-) create mode 100644 src/x86.c create mode 100644 src/x86.h
diff --git a/Makefile b/Makefile index 9b7ed33..46df1c6 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ OUT=out/
# Source files -SRCBOTH=misc.c stacks.c output.c util.c block.c cdrom.c mouse.c kbd.c \ +SRCBOTH=misc.c stacks.c output.c util.c x86.c block.c cdrom.c mouse.c kbd.c \ serial.c clock.c resume.c pnpbios.c vgahooks.c pcibios.c apm.c \ fw/smp.c \ hw/pci.c hw/timer.c hw/pic.c hw/ps2port.c \ diff --git a/src/bregs.h b/src/bregs.h index 577effc..009db99 100644 --- a/src/bregs.h +++ b/src/bregs.h @@ -7,29 +7,15 @@ #ifndef __BREGS_H #define __BREGS_H
-// CPU flag bitdefs -#define F_CF (1<<0) -#define F_ZF (1<<6) -#define F_IF (1<<9) -#define F_ID (1<<21) - -// CR0 flags -#define CR0_PG (1<<31) // Paging -#define CR0_CD (1<<30) // Cache disable -#define CR0_NW (1<<29) // Not Write-through -#define CR0_PE (1<<0) // Protection enable - - -#ifndef __ASSEMBLY__ - +#include "types.h" // u16 #include "farptr.h" // struct segoff_s +#include "x86.h" // F_CF +
/**************************************************************** * Registers saved/restored in romlayout.S ****************************************************************/
-#include "types.h" // u16 - #define UREG(ER, R, RH, RL) union { u32 ER; struct { u16 R; u16 R ## _hi; }; struct { u8 RL; u8 RH; u8 R ## _hilo; u8 R ## _hihi; }; }
// Layout of registers passed in to irq handlers. Note that this @@ -92,6 +78,4 @@ set_code_invalid_silent(struct bregs *regs, u8 code) set_cf(regs, 1); }
-#endif // !__ASSEMBLY__ - #endif // bregs.h diff --git a/src/fw/acpi.c b/src/fw/acpi.c index 9fd1c05..fcf11ea 100644 --- a/src/fw/acpi.c +++ b/src/fw/acpi.c @@ -15,6 +15,7 @@ #include "config.h" // CONFIG_* #include "paravirt.h" // RamSize #include "dev-q35.h" +#include "x86.h" // readl
#include "src/fw/acpi-dsdt.hex"
diff --git a/src/fw/mptable.c b/src/fw/mptable.c index 2d12865..47fe53d 100644 --- a/src/fw/mptable.c +++ b/src/fw/mptable.c @@ -10,6 +10,7 @@ #include "mptable.h" // MPTABLE_SIGNATURE #include "hw/pci.h" #include "hw/pci_regs.h" +#include "x86.h" // cpuid
void mptable_setup(void) diff --git a/src/fw/mtrr.c b/src/fw/mtrr.c index 001e275..855457a 100644 --- a/src/fw/mtrr.c +++ b/src/fw/mtrr.c @@ -8,6 +8,7 @@ #include "config.h" // CONFIG_* #include "hw/pci.h" // pcimem_start #include "paravirt.h" // RamSize +#include "x86.h" // cpuid
#define MSR_MTRRcap 0x000000fe #define MSR_MTRRfix64K_00000 0x00000250 diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index b1dd8b0..a68e3a1 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -20,6 +20,7 @@ #include "mptable.h" // mptable_setup #include "hw/pci.h" // create_pirtable #include "xen.h" // xen_biostable_setup +#include "x86.h" // cpuid
// Amount of continuous ram under 4Gig u32 RamSize; diff --git a/src/fw/shadow.c b/src/fw/shadow.c index 67e943f..767c6ea 100644 --- a/src/fw/shadow.c +++ b/src/fw/shadow.c @@ -12,6 +12,7 @@ #include "hw/pci_regs.h" // PCI_VENDOR_ID #include "paravirt.h" // runningOnXen #include "dev-q35.h" // PCI_VENDOR_ID_INTEL +#include "x86.h" // wbinvd
// On the emulators, the bios at 0xf0000 is also at 0xffff0000 #define BIOS_SRC_OFFSET 0xfff00000 diff --git a/src/fw/smbios.c b/src/fw/smbios.c index fd63afb..93fb57f 100644 --- a/src/fw/smbios.c +++ b/src/fw/smbios.c @@ -9,6 +9,7 @@ #include "config.h" // CONFIG_* #include "paravirt.h" // RamSize #include "smbios.h" // struct smbios_entry_point +#include "x86.h" // cpuid
struct smbios_entry_point *SMBiosAddr;
diff --git a/src/fw/smm.c b/src/fw/smm.c index 3f01207..3a1a799 100644 --- a/src/fw/smm.c +++ b/src/fw/smm.c @@ -7,11 +7,12 @@
#include "hw/pci.h" // pci_config_writel #include "hw/pci_regs.h" // PCI_DEVICE_ID -#include "util.h" // wbinvd +#include "util.h" // dprintf #include "config.h" // CONFIG_* #include "ioport.h" // outb #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL #include "dev-q35.h" +#include "x86.h" // wbinvd
extern u8 smm_relocation_start, smm_relocation_end; ASM32FLAT( diff --git a/src/fw/smp.c b/src/fw/smp.c index 6379d36..a8504ab 100644 --- a/src/fw/smp.c +++ b/src/fw/smp.c @@ -8,6 +8,7 @@ #include "util.h" // dprintf #include "config.h" // CONFIG_* #include "hw/cmos.h" // CMOS_BIOS_SMP_COUNT +#include "x86.h" // wrmsr
#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300) #define APIC_SVR ((u8*)BUILD_APIC_ADDR + 0x0F0) diff --git a/src/fw/xen.c b/src/fw/xen.c index 5dfee9e..6e21bff 100644 --- a/src/fw/xen.c +++ b/src/fw/xen.c @@ -11,6 +11,7 @@ #include "types.h" // ASM32FLAT #include "util.h" // copy_acpi_rsdp #include "acpi.h" // find_acpi_features +#include "x86.h" // cpuid
#define INFO_PHYSICAL_ADDRESS 0x00001000
diff --git a/src/hw/pci.c b/src/hw/pci.c index dc62c5c..d1115a4 100644 --- a/src/hw/pci.c +++ b/src/hw/pci.c @@ -12,6 +12,7 @@ #include "farptr.h" // MAKE_FLATPTR #include "pci_regs.h" // PCI_VENDOR_ID #include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA +#include "x86.h" // readl
void pci_config_writel(u16 bdf, u32 addr, u32 val) { diff --git a/src/hw/timer.c b/src/hw/timer.c index b368362..2547639 100644 --- a/src/hw/timer.c +++ b/src/hw/timer.c @@ -9,6 +9,7 @@ #include "ioport.h" // PORT_PIT_MODE #include "config.h" // CONFIG_* #include "biosvar.h" // GET_LOW +#include "x86.h" // cpuid
// Bits for PORT_PS2_CTRLB #define PPCB_T2GATE (1<<0) diff --git a/src/hw/usb-ehci.c b/src/hw/usb-ehci.c index 978ca68..333679e 100644 --- a/src/hw/usb-ehci.c +++ b/src/hw/usb-ehci.c @@ -15,6 +15,7 @@ #include "biosvar.h" // GET_LOWFLAT #include "usb-uhci.h" // uhci_setup #include "usb-ohci.h" // ohci_setup +#include "x86.h" // readl
struct usb_ehci_s { struct usb_s usb; diff --git a/src/hw/usb-ohci.c b/src/hw/usb-ohci.c index e5c9fa5..c1806ff 100644 --- a/src/hw/usb-ohci.c +++ b/src/hw/usb-ohci.c @@ -11,6 +11,7 @@ #include "pci_regs.h" // PCI_BASE_ADDRESS_0 #include "usb.h" // struct usb_s #include "biosvar.h" // GET_LOWFLAT +#include "x86.h" // readl
#define FIT (1 << 31)
diff --git a/src/hw/usb.c b/src/hw/usb.c index 42541ff..647359e 100644 --- a/src/hw/usb.c +++ b/src/hw/usb.c @@ -18,6 +18,7 @@ #include "usb-uas.h" // usb_uas_setup #include "usb.h" // struct usb_s #include "biosvar.h" // GET_GLOBAL +#include "x86.h" // __fls
/**************************************************************** diff --git a/src/pmm.c b/src/pmm.c index 9ea4313..c86d66f 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -11,6 +11,7 @@ #include "biosvar.h" // GET_BDA #include "optionroms.h" // OPTION_ROM_ALIGN #include "list.h" // hlist_node +#include "x86.h" // __ffs
// Information on a reserved area. struct allocinfo_s { diff --git a/src/romlayout.S b/src/romlayout.S index cc97f9a..17904ae 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -7,7 +7,7 @@
#include "config.h" // CONFIG_* #include "ioport.h" // PORT_A20 -#include "bregs.h" // CR0_* +#include "x86.h" // CR0_* #include "hw/cmos.h" // CMOS_RESET_CODE #include "asm-offsets.h" // BREGS_* #include "entryfuncs.S" // ENTRY_* diff --git a/src/util.c b/src/util.c index ffabd1c..dd7afdf 100644 --- a/src/util.c +++ b/src/util.c @@ -8,22 +8,6 @@ #include "bregs.h" // struct bregs #include "config.h" // BUILD_STACK_ADDR
-void -cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) -{ - // Check for cpu id - u32 origflags = save_flags(); - restore_flags(origflags ^ F_ID); - u32 newflags = save_flags(); - restore_flags(origflags); - - if (((origflags ^ newflags) & F_ID) != F_ID) - // no cpuid - *eax = *ebx = *ecx = *edx = 0; - else - __cpuid(index, eax, ebx, ecx, edx); -} -
/**************************************************************** * String ops diff --git a/src/util.h b/src/util.h index f2a1671..70114a6 100644 --- a/src/util.h +++ b/src/util.h @@ -8,148 +8,7 @@
#include "types.h" // u32
-static inline void irq_disable(void) -{ - asm volatile("cli": : :"memory"); -} - -static inline void irq_enable(void) -{ - asm volatile("sti": : :"memory"); -} - -static inline u32 save_flags(void) -{ - u32 flags; - asm volatile("pushfl ; popl %0" : "=rm" (flags)); - return flags; -} - -static inline void restore_flags(u32 flags) -{ - asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc"); -} - -static inline void cpu_relax(void) -{ - asm volatile("rep ; nop": : :"memory"); -} - -static inline void nop(void) -{ - asm volatile("nop"); -} - -static inline void hlt(void) -{ - asm volatile("hlt": : :"memory"); -} - -static inline void wbinvd(void) -{ - asm volatile("wbinvd": : :"memory"); -} - -#define CPUID_TSC (1 << 4) -#define CPUID_MSR (1 << 5) -#define CPUID_APIC (1 << 9) -#define CPUID_MTRR (1 << 12) -static inline void __cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) -{ - asm("cpuid" - : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) - : "0" (index)); -} - -static inline u32 getcr0(void) { - u32 cr0; - asm("movl %%cr0, %0" : "=r"(cr0)); - return cr0; -} -static inline void setcr0(u32 cr0) { - asm("movl %0, %%cr0" : : "r"(cr0)); -} - -static inline u64 rdmsr(u32 index) -{ - u64 ret; - asm ("rdmsr" : "=A"(ret) : "c"(index)); - return ret; -} - -static inline void wrmsr(u32 index, u64 val) -{ - asm volatile ("wrmsr" : : "c"(index), "A"(val)); -} - -static inline u64 rdtscll(void) -{ - u64 val; - asm volatile("rdtsc" : "=A" (val)); - return val; -} - -static inline u32 __ffs(u32 word) -{ - asm("bsf %1,%0" - : "=r" (word) - : "rm" (word)); - return word; -} -static inline u32 __fls(u32 word) -{ - asm("bsr %1,%0" - : "=r" (word) - : "rm" (word)); - return word; -} - -static inline u32 getesp(void) { - u32 esp; - asm("movl %%esp, %0" : "=rm"(esp)); - return esp; -} - -static inline void writel(void *addr, u32 val) { - *(volatile u32 *)addr = val; -} -static inline void writew(void *addr, u16 val) { - *(volatile u16 *)addr = val; -} -static inline void writeb(void *addr, u8 val) { - *(volatile u8 *)addr = val; -} -static inline u32 readl(const void *addr) { - return *(volatile const u32 *)addr; -} -static inline u16 readw(const void *addr) { - return *(volatile const u16 *)addr; -} -static inline u8 readb(const void *addr) { - return *(volatile const u8 *)addr; -} - -// GDT bits -#define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set -#define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set -#define GDT_B (0x1ULL << 54) // Big flag -#define GDT_G (0x1ULL << 55) // Granularity flag -// GDT bits for segment base -#define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \ - | (((u64)(v) & 0x00ffffff) << 16)) -// GDT bits for segment limit (0-1Meg) -#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \ - | (((u64)(v) & 0x0000ffff) << 0)) -// GDT bits for segment limit (0-4Gig in 4K chunks) -#define GDT_GRANLIMIT(v) (GDT_G | GDT_LIMIT((v) >> 12)) - -struct descloc_s { - u16 length; - u32 addr; -} PACKED; - // util.c -void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); u8 checksum_far(u16 buf_seg, void *buf_far, u32 len); u8 checksum(void *buf, u32 len); size_t strlen(const char *s); diff --git a/src/x86.c b/src/x86.c new file mode 100644 index 0000000..0fdf86f --- /dev/null +++ b/src/x86.c @@ -0,0 +1,23 @@ +// X86 utility functions. +// +// Copyright (C) 2013 Kevin O'Connor kevin@koconnor.net +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "x86.h" // __cpuid + +void +cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ + // Check for cpu id + u32 origflags = save_flags(); + restore_flags(origflags ^ F_ID); + u32 newflags = save_flags(); + restore_flags(origflags); + + if (((origflags ^ newflags) & F_ID) != F_ID) + // no cpuid + *eax = *ebx = *ecx = *edx = 0; + else + __cpuid(index, eax, ebx, ecx, edx); +} diff --git a/src/x86.h b/src/x86.h new file mode 100644 index 0000000..389d747 --- /dev/null +++ b/src/x86.h @@ -0,0 +1,168 @@ +// Basic x86 asm functions. +#ifndef __X86_H +#define __X86_H + +// CPU flag bitdefs +#define F_CF (1<<0) +#define F_ZF (1<<6) +#define F_IF (1<<9) +#define F_ID (1<<21) + +// CR0 flags +#define CR0_PG (1<<31) // Paging +#define CR0_CD (1<<30) // Cache disable +#define CR0_NW (1<<29) // Not Write-through +#define CR0_PE (1<<0) // Protection enable + +#ifndef __ASSEMBLY__ + +#include "types.h" // u32 + +static inline void irq_disable(void) +{ + asm volatile("cli": : :"memory"); +} + +static inline void irq_enable(void) +{ + asm volatile("sti": : :"memory"); +} + +static inline u32 save_flags(void) +{ + u32 flags; + asm volatile("pushfl ; popl %0" : "=rm" (flags)); + return flags; +} + +static inline void restore_flags(u32 flags) +{ + asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc"); +} + +static inline void cpu_relax(void) +{ + asm volatile("rep ; nop": : :"memory"); +} + +static inline void nop(void) +{ + asm volatile("nop"); +} + +static inline void hlt(void) +{ + asm volatile("hlt": : :"memory"); +} + +static inline void wbinvd(void) +{ + asm volatile("wbinvd": : :"memory"); +} + +#define CPUID_TSC (1 << 4) +#define CPUID_MSR (1 << 5) +#define CPUID_APIC (1 << 9) +#define CPUID_MTRR (1 << 12) +static inline void __cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) +{ + asm("cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (index)); +} + +static inline u32 getcr0(void) { + u32 cr0; + asm("movl %%cr0, %0" : "=r"(cr0)); + return cr0; +} +static inline void setcr0(u32 cr0) { + asm("movl %0, %%cr0" : : "r"(cr0)); +} + +static inline u64 rdmsr(u32 index) +{ + u64 ret; + asm ("rdmsr" : "=A"(ret) : "c"(index)); + return ret; +} + +static inline void wrmsr(u32 index, u64 val) +{ + asm volatile ("wrmsr" : : "c"(index), "A"(val)); +} + +static inline u64 rdtscll(void) +{ + u64 val; + asm volatile("rdtsc" : "=A" (val)); + return val; +} + +static inline u32 __ffs(u32 word) +{ + asm("bsf %1,%0" + : "=r" (word) + : "rm" (word)); + return word; +} +static inline u32 __fls(u32 word) +{ + asm("bsr %1,%0" + : "=r" (word) + : "rm" (word)); + return word; +} + +static inline u32 getesp(void) { + u32 esp; + asm("movl %%esp, %0" : "=rm"(esp)); + return esp; +} + +static inline void writel(void *addr, u32 val) { + *(volatile u32 *)addr = val; +} +static inline void writew(void *addr, u16 val) { + *(volatile u16 *)addr = val; +} +static inline void writeb(void *addr, u8 val) { + *(volatile u8 *)addr = val; +} +static inline u32 readl(const void *addr) { + return *(volatile const u32 *)addr; +} +static inline u16 readw(const void *addr) { + return *(volatile const u16 *)addr; +} +static inline u8 readb(const void *addr) { + return *(volatile const u8 *)addr; +} + +// GDT bits +#define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set +#define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set +#define GDT_B (0x1ULL << 54) // Big flag +#define GDT_G (0x1ULL << 55) // Granularity flag +// GDT bits for segment base +#define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \ + | (((u64)(v) & 0x00ffffff) << 16)) +// GDT bits for segment limit (0-1Meg) +#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \ + | (((u64)(v) & 0x0000ffff) << 0)) +// GDT bits for segment limit (0-4Gig in 4K chunks) +#define GDT_GRANLIMIT(v) (GDT_G | GDT_LIMIT((v) >> 12)) + +struct descloc_s { + u16 length; + u32 addr; +} PACKED; + + +// x86.c +void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); + + +#endif // !__ASSEMBLY__ + +#endif // x86.h