diff options
author | Stefan Reinauer <stepan@coreboot.org> | 2010-12-11 20:33:41 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2010-12-11 20:33:41 +0000 |
commit | 8677a23d5b053d550f70246de9c7dc8fd4e2fbf9 (patch) | |
tree | d9a7c6042de85d623739e2679ba90c66aad2797f /src/arch/x86/include | |
parent | 198cb96387c457affa01696405ffaa4531e8e361 (diff) |
After this has been brought up many times before, rename src/arch/i386 to
src/arch/x86.
Signed-off-by: Stefan Reinauer <stepan@coreboot.org>
Acked-by: Patrick Georgi <patrick@georgi-clan.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6161 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/x86/include')
27 files changed, 2141 insertions, 0 deletions
diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h new file mode 100644 index 0000000000..030745d5ab --- /dev/null +++ b/src/arch/x86/include/arch/acpi.h @@ -0,0 +1,440 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2004 SUSE LINUX AG + * Copyright (C) 2004 Nick Barker + * Copyright (C) 2008-2009 coresystems GmbH + * (Written by Stefan Reinauer <stepan@coresystems.de>) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * coreboot ACPI support - headers and defines. + */ + +#ifndef __ASM_ACPI_H +#define __ASM_ACPI_H + +#if CONFIG_GENERATE_ACPI_TABLES==1 + +#include <stdint.h> + +#define RSDP_SIG "RSD PTR " /* RSDT pointer signature */ +#define ACPI_TABLE_CREATOR "COREBOOT" /* Must be exactly 8 bytes long! */ +#define OEM_ID "CORE " /* Must be exactly 6 bytes long! */ +#define ASLC "CORE" /* Must be exactly 4 bytes long! */ + +/* RSDP (Root System Description Pointer) */ +typedef struct acpi_rsdp { + char signature[8]; /* RSDP signature */ + u8 checksum; /* Checksum of the first 20 bytes */ + char oem_id[6]; /* OEM ID */ + u8 revision; /* 0 for ACPI 1.0, 2 for ACPI 2.0/3.0/4.0 */ + u32 rsdt_address; /* Physical address of RSDT (32 bits) */ + u32 length; /* Total RSDP length (incl. extended part) */ + u64 xsdt_address; /* Physical address of XSDT (64 bits) */ + u8 ext_checksum; /* Checksum of the whole table */ + u8 reserved[3]; +} __attribute__ ((packed)) acpi_rsdp_t; +/* Note: ACPI 1.0 didn't have length, xsdt_address, and ext_checksum. */ + +/* GAS (Generic Address Structure) */ +typedef struct acpi_gen_regaddr { + u8 space_id; /* Address space ID */ + u8 bit_width; /* Register size in bits */ + u8 bit_offset; /* Register bit offset */ + u8 resv; /* FIXME: Access size in ACPI 2.0/3.0/4.0 */ + u32 addrl; /* Register address, low 32 bits */ + u32 addrh; /* Register address, high 32 bits */ +} __attribute__ ((packed)) acpi_addr_t; + +#define ACPI_ADDRESS_SPACE_MEMORY 0 /* System memory */ +#define ACPI_ADDRESS_SPACE_IO 1 /* System I/O */ +#define ACPI_ADDRESS_SPACE_PCI 2 /* PCI config space */ +#define ACPI_ADDRESS_SPACE_EC 3 /* Embedded controller */ +#define ACPI_ADDRESS_SPACE_SMBUS 4 /* SMBus */ +#define ACPI_ADDRESS_SPACE_FIXED 0x7f /* Functional fixed hardware */ +/* 0x80-0xbf: Reserved */ +/* 0xc0-0xff: OEM defined */ + +/* Generic ACPI header, provided by (almost) all tables */ +typedef struct acpi_table_header { + char signature[4]; /* ACPI signature (4 ASCII characters) */ + u32 length; /* Table length in bytes (incl. header) */ + u8 revision; /* Table version (not ACPI version!) */ + u8 checksum; /* To make sum of entire table == 0 */ + char oem_id[6]; /* OEM identification */ + char oem_table_id[8]; /* OEM table identification */ + u32 oem_revision; /* OEM revision number */ + char asl_compiler_id[4]; /* ASL compiler vendor ID */ + u32 asl_compiler_revision; /* ASL compiler revision number */ +} __attribute__ ((packed)) acpi_header_t; + +/* A maximum number of 32 ACPI tables ought to be enough for now. */ +#define MAX_ACPI_TABLES 32 + +/* RSDT (Root System Description Table) */ +typedef struct acpi_rsdt { + struct acpi_table_header header; + u32 entry[MAX_ACPI_TABLES]; +} __attribute__ ((packed)) acpi_rsdt_t; + +/* XSDT (Extended System Description Table) */ +typedef struct acpi_xsdt { + struct acpi_table_header header; + u64 entry[MAX_ACPI_TABLES]; +} __attribute__ ((packed)) acpi_xsdt_t; + +/* HPET timers */ +typedef struct acpi_hpet { + struct acpi_table_header header; + u32 id; + struct acpi_gen_regaddr addr; + u8 number; + u16 min_tick; + u8 attributes; +} __attribute__ ((packed)) acpi_hpet_t; + +/* MCFG (PCI Express MMIO config space BAR description table) */ +typedef struct acpi_mcfg { + struct acpi_table_header header; + u8 reserved[8]; +} __attribute__ ((packed)) acpi_mcfg_t; + +typedef struct acpi_mcfg_mmconfig { + u32 base_address; + u32 base_reserved; + u16 pci_segment_group_number; + u8 start_bus_number; + u8 end_bus_number; + u8 reserved[4]; +} __attribute__ ((packed)) acpi_mcfg_mmconfig_t; + +/* SRAT (System Resource Affinity Table) */ +typedef struct acpi_srat { + struct acpi_table_header header; + u32 resv; + u64 resv1; + /* Followed by static resource allocation structure[n] */ +} __attribute__ ((packed)) acpi_srat_t; + +/* SRAT: Processor Local APIC/SAPIC Affinity Structure */ +typedef struct acpi_srat_lapic { + u8 type; /* Type (0) */ + u8 length; /* Length in bytes (16) */ + u8 proximity_domain_7_0; /* Proximity domain bits[7:0] */ + u8 apic_id; /* Local APIC ID */ + u32 flags; /* Enable bit 0 = 1, other bits reserved to 0 */ + u8 local_sapic_eid; /* Local SAPIC EID */ + u8 proximity_domain_31_8[3]; /* Proximity domain bits[31:8] */ + u32 resv; /* TODO: Clock domain in ACPI 4.0. */ +} __attribute__ ((packed)) acpi_srat_lapic_t; + +/* SRAT: Memory Affinity Structure */ +typedef struct acpi_srat_mem { + u8 type; /* Type (1) */ + u8 length; /* Length in bytes (40) */ + u32 proximity_domain; /* Proximity domain */ + u16 resv; + u32 base_address_low; /* Mem range base address, low */ + u32 base_address_high; /* Mem range base address, high */ + u32 length_low; /* Mem range length, low */ + u32 length_high; /* Mem range length, high */ + u32 resv1; + u32 flags; /* Enable bit 0, hot pluggable bit 1; Non Volatile bit 2, other bits reserved to 0 */ + u32 resv2[2]; +} __attribute__ ((packed)) acpi_srat_mem_t; + +/* SLIT (System Locality Distance Information Table) */ +typedef struct acpi_slit { + struct acpi_table_header header; + /* Followed by static resource allocation 8+byte[num*num] */ +} __attribute__ ((packed)) acpi_slit_t; + +/* MADT (Multiple APIC Description Table) */ +typedef struct acpi_madt { + struct acpi_table_header header; + u32 lapic_addr; /* Local APIC address */ + u32 flags; /* Multiple APIC flags */ +} __attribute__ ((packed)) acpi_madt_t; + +/* MADT: APIC Structure Types */ +/* TODO: Convert to ALLCAPS. */ +enum acpi_apic_types { + LocalApic = 0, /* Processor local APIC */ + IOApic = 1, /* I/O APIC */ + IRQSourceOverride = 2, /* Interrupt source override */ + NMIType = 3, /* NMI source */ + LocalApicNMI = 4, /* Local APIC NMI */ + LApicAddressOverride = 5, /* Local APIC address override */ + IOSApic = 6, /* I/O SAPIC */ + LocalSApic = 7, /* Local SAPIC */ + PlatformIRQSources = 8, /* Platform interrupt sources */ + Localx2Apic = 9, /* Processor local x2APIC */ + Localx2ApicNMI = 10, /* Local x2APIC NMI */ + /* 0x0b-0x7f: Reserved */ + /* 0x80-0xff: Reserved for OEM use */ +}; + +/* MADT: Processor Local APIC Structure */ +typedef struct acpi_madt_lapic { + u8 type; /* Type (0) */ + u8 length; /* Length in bytes (8) */ + u8 processor_id; /* ACPI processor ID */ + u8 apic_id; /* Local APIC ID */ + u32 flags; /* Local APIC flags */ +} __attribute__ ((packed)) acpi_madt_lapic_t; + +/* MADT: Local APIC NMI Structure */ +typedef struct acpi_madt_lapic_nmi { + u8 type; /* Type (4) */ + u8 length; /* Length in bytes (6) */ + u8 processor_id; /* ACPI processor ID */ + u16 flags; /* MPS INTI flags */ + u8 lint; /* Local APIC LINT# */ +} __attribute__ ((packed)) acpi_madt_lapic_nmi_t; + +/* MADT: I/O APIC Structure */ +typedef struct acpi_madt_ioapic { + u8 type; /* Type (1) */ + u8 length; /* Length in bytes (12) */ + u8 ioapic_id; /* I/O APIC ID */ + u8 reserved; + u32 ioapic_addr; /* I/O APIC address */ + u32 gsi_base; /* Global system interrupt base */ +} __attribute__ ((packed)) acpi_madt_ioapic_t; + +/* MADT: Interrupt Source Override Structure */ +typedef struct acpi_madt_irqoverride { + u8 type; /* Type (2) */ + u8 length; /* Length in bytes (10) */ + u8 bus; /* ISA (0) */ + u8 source; /* Bus-relative int. source (IRQ) */ + u32 gsirq; /* Global system interrupt */ + u16 flags; /* MPS INTI flags */ +} __attribute__ ((packed)) acpi_madt_irqoverride_t; + +/* FADT (Fixed ACPI Description Table) */ +typedef struct acpi_fadt { + struct acpi_table_header header; + u32 firmware_ctrl; + u32 dsdt; + u8 model; + u8 preferred_pm_profile; + u16 sci_int; + u32 smi_cmd; + u8 acpi_enable; + u8 acpi_disable; + u8 s4bios_req; + u8 pstate_cnt; + u32 pm1a_evt_blk; + u32 pm1b_evt_blk; + u32 pm1a_cnt_blk; + u32 pm1b_cnt_blk; + u32 pm2_cnt_blk; + u32 pm_tmr_blk; + u32 gpe0_blk; + u32 gpe1_blk; + u8 pm1_evt_len; + u8 pm1_cnt_len; + u8 pm2_cnt_len; + u8 pm_tmr_len; + u8 gpe0_blk_len; + u8 gpe1_blk_len; + u8 gpe1_base; + u8 cst_cnt; + u16 p_lvl2_lat; + u16 p_lvl3_lat; + u16 flush_size; + u16 flush_stride; + u8 duty_offset; + u8 duty_width; + u8 day_alrm; + u8 mon_alrm; + u8 century; + u16 iapc_boot_arch; + u8 res2; + u32 flags; + struct acpi_gen_regaddr reset_reg; + u8 reset_value; + u8 res3; + u8 res4; + u8 res5; + u32 x_firmware_ctl_l; + u32 x_firmware_ctl_h; + u32 x_dsdt_l; + u32 x_dsdt_h; + struct acpi_gen_regaddr x_pm1a_evt_blk; + struct acpi_gen_regaddr x_pm1b_evt_blk; + struct acpi_gen_regaddr x_pm1a_cnt_blk; + struct acpi_gen_regaddr x_pm1b_cnt_blk; + struct acpi_gen_regaddr x_pm2_cnt_blk; + struct acpi_gen_regaddr x_pm_tmr_blk; + struct acpi_gen_regaddr x_gpe0_blk; + struct acpi_gen_regaddr x_gpe1_blk; +} __attribute__ ((packed)) acpi_fadt_t; + +/* FADT Feature Flags */ +#define ACPI_FADT_WBINVD (1 << 0) +#define ACPI_FADT_WBINVD_FLUSH (1 << 1) +#define ACPI_FADT_C1_SUPPORTED (1 << 2) +#define ACPI_FADT_C2_MP_SUPPORTED (1 << 3) +#define ACPI_FADT_POWER_BUTTON (1 << 4) +#define ACPI_FADT_SLEEP_BUTTON (1 << 5) +#define ACPI_FADT_FIXED_RTC (1 << 6) +#define ACPI_FADT_S4_RTC_WAKE (1 << 7) +#define ACPI_FADT_32BIT_TIMER (1 << 8) +#define ACPI_FADT_DOCKING_SUPPORTED (1 << 9) +#define ACPI_FADT_RESET_REGISTER (1 << 10) +#define ACPI_FADT_SEALED_CASE (1 << 11) +#define ACPI_FADT_HEADLESS (1 << 12) +#define ACPI_FADT_SLEEP_TYPE (1 << 13) +#define ACPI_FADT_PCI_EXPRESS_WAKE (1 << 14) +#define ACPI_FADT_PLATFORM_CLOCK (1 << 15) +#define ACPI_FADT_S4_RTC_VALID (1 << 16) +#define ACPI_FADT_REMOTE_POWER_ON (1 << 17) +#define ACPI_FADT_APIC_CLUSTER (1 << 18) +#define ACPI_FADT_APIC_PHYSICAL (1 << 19) +/* Bits 20-31: reserved */ + +/* FADT Boot Architecture Flags */ +#define ACPI_FADT_LEGACY_DEVICES (1 << 0) +#define ACPI_FADT_8042 (1 << 1) +#define ACPI_FADT_VGA_NOT_PRESENT (1 << 2) +#define ACPI_FADT_MSI_NOT_SUPPORTED (1 << 3) +#define ACPI_FADT_NO_PCIE_ASPM_CONTROL (1 << 4) + +/* FADT Preferred Power Management Profile */ +enum acpi_preferred_pm_profiles { + PM_UNSPECIFIED = 0, + PM_DESKTOP = 1, + PM_MOBILE = 2, + PM_WORKSTATION = 3, + PM_ENTERPRISE_SERVER = 4, + PM_SOHO_SERVER = 5, + PM_APPLIANCE_PC = 6, + PM_PERFORMANCE_SERVER = 7, +}; + +/* FACS (Firmware ACPI Control Structure) */ +typedef struct acpi_facs { + char signature[4]; /* "FACS" */ + u32 length; /* Length in bytes (>= 64) */ + u32 hardware_signature; /* Hardware signature */ + u32 firmware_waking_vector; /* Firmware waking vector */ + u32 global_lock; /* Global lock */ + u32 flags; /* FACS flags */ + u32 x_firmware_waking_vector_l; /* X FW waking vector, low */ + u32 x_firmware_waking_vector_h; /* X FW waking vector, high */ + u8 version; /* ACPI 4.0: 2 */ + u8 resv[31]; /* FIXME: 4.0: ospm_flags */ +} __attribute__ ((packed)) acpi_facs_t; + +/* FACS flags */ +#define ACPI_FACS_S4BIOS_F (1 << 0) +#define ACPI_FACS_64BIT_WAKE_F (1 << 1) +/* Bits 31..2: reserved */ + +/* ECDT (Embedded Controller Boot Resources Table) */ +typedef struct acpi_ecdt { + struct acpi_table_header header; + struct acpi_gen_regaddr ec_control; /* EC control register */ + struct acpi_gen_regaddr ec_data; /* EC data register */ + u32 uid; /* UID */ + u8 gpe_bit; /* GPE bit */ + u8 ec_id[]; /* EC ID */ +} __attribute__ ((packed)) acpi_ecdt_t; + +/* These are implemented by the target port or north/southbridge. */ +unsigned long write_acpi_tables(unsigned long addr); +unsigned long acpi_fill_madt(unsigned long current); +unsigned long acpi_fill_mcfg(unsigned long current); +unsigned long acpi_fill_srat(unsigned long current); +unsigned long acpi_fill_slit(unsigned long current); +unsigned long acpi_fill_ssdt_generator(unsigned long current, + const char *oem_table_id); +void acpi_create_ssdt_generator(acpi_header_t *ssdt, const char *oem_table_id); +void acpi_create_fadt(acpi_fadt_t *fadt,acpi_facs_t *facs, void *dsdt); + +void update_ssdt(void *ssdt); +void update_ssdtx(void *ssdtx, int i); + +/* These can be used by the target port. */ +u8 acpi_checksum(u8 *table, u32 length); + +void acpi_add_table(acpi_rsdp_t *rsdp, void *table); + +int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic); +int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr, + u32 gsi_base); +int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride, + u8 bus, u8 source, u32 gsirq, u16 flags); +int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu, + u16 flags, u8 lint); +void acpi_create_madt(acpi_madt_t *madt); +unsigned long acpi_create_madt_lapics(unsigned long current); +unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, + u8 lint); + +int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic); +int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek,u32 sizek, + u32 flags); +int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base, + u16 seg_nr, u8 start, u8 end); +unsigned long acpi_create_srat_lapics(unsigned long current); +void acpi_create_srat(acpi_srat_t *srat); + +void acpi_create_slit(acpi_slit_t *slit); + +void acpi_create_hpet(acpi_hpet_t *hpet); + +void acpi_create_mcfg(acpi_mcfg_t *mcfg); + +void acpi_create_facs(acpi_facs_t *facs); + +#if CONFIG_HAVE_ACPI_SLIC +unsigned long acpi_create_slic(unsigned long current); +#endif + +void acpi_write_rsdt(acpi_rsdt_t *rsdt); +void acpi_write_xsdt(acpi_xsdt_t *xsdt); +void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt, acpi_xsdt_t *xsdt); + +#if CONFIG_HAVE_ACPI_RESUME +/* 0 = S0, 1 = S1 ...*/ +extern u8 acpi_slp_type; + +void suspend_resume(void); +void *acpi_find_wakeup_vector(void); +void *acpi_get_wakeup_rsdp(void); +void acpi_jump_to_wakeup(void *wakeup_addr); + +int acpi_get_sleep_type(void); + +#endif + +/* northbridge/amd/amdfam10/amdfam10_acpi.c */ +unsigned long acpi_add_ssdt_pstates(acpi_rsdp_t *rsdp, unsigned long current); + +/* cpu/intel/speedstep/acpi.c */ +void generate_cpu_entries(void); + +#else // CONFIG_GENERATE_ACPI_TABLES + +#define write_acpi_tables(start) (start) + +#endif + +#endif diff --git a/src/arch/x86/include/arch/acpigen.h b/src/arch/x86/include/arch/acpigen.h new file mode 100644 index 0000000000..6f13a7ae1f --- /dev/null +++ b/src/arch/x86/include/arch/acpigen.h @@ -0,0 +1,56 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBACPI_H +#define LIBACPI_H + +#include <assert.h> +#include <stdlib.h> +#include <stdint.h> + +void acpigen_patch_len(int len); +void acpigen_set_current(char *curr); +char *acpigen_get_current(void); +int acpigen_write_package(int nr_el); +int acpigen_write_byte(unsigned int data); +int acpigen_emit_byte(unsigned char data); +int acpigen_emit_stream(const char *data, int size); +int acpigen_emit_namestring(const char *namepath); +int acpigen_write_dword(unsigned int data); +int acpigen_write_qword(uint64_t data); +int acpigen_write_name(const char *name); +int acpigen_write_name_dword(const char *name, uint32_t val); +int acpigen_write_name_qword(const char *name, uint64_t val); +int acpigen_write_name_byte(const char *name, uint8_t val); +int acpigen_write_scope(const char *name); +int acpigen_write_PPC(u8 nr); +int acpigen_write_empty_PCT(void); +int acpigen_write_PSS_package(u32 coreFreq, u32 power, u32 transLat, u32 busmLat, + u32 control, u32 status); +typedef enum { SW_ALL=0xfc, SW_ANY=0xfd, HW_ALL=0xfe } PSD_coord; +int acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype); +int acpigen_write_processor(u8 cpuindex, u32 pblock_addr, u8 pblock_len); +int acpigen_write_mem32fixed(int readwrite, u32 base, u32 size); +int acpigen_write_io16(u16 min, u16 max, u8 align, u8 len, u8 decode16); +int acpigen_write_resourcetemplate_header(void); +int acpigen_write_resourcetemplate_footer(int len); +int acpigen_write_mainboard_resource_template(void); +int acpigen_write_mainboard_resources(const char *scope, const char *name); + +#endif diff --git a/src/arch/x86/include/arch/boot/boot.h b/src/arch/x86/include/arch/boot/boot.h new file mode 100644 index 0000000000..3ff51c3082 --- /dev/null +++ b/src/arch/x86/include/arch/boot/boot.h @@ -0,0 +1,8 @@ +#ifndef ASM_I386_BOOT_H +#define ASM_I386_BOOT_H + +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_386 + +#endif /* ASM_I386_BOOT_H */ diff --git a/src/arch/x86/include/arch/byteorder.h b/src/arch/x86/include/arch/byteorder.h new file mode 100644 index 0000000000..ab344e6394 --- /dev/null +++ b/src/arch/x86/include/arch/byteorder.h @@ -0,0 +1,20 @@ +#ifndef _BYTEORDER_H +#define _BYTEORDER_H + +#define __LITTLE_ENDIAN 1234 + +#include <swab.h> + +#define cpu_to_le32(x) ((unsigned int)(x)) +#define le32_to_cpu(x) ((unsigned int)(x)) +#define cpu_to_le16(x) ((unsigned short)(x)) +#define le16_to_cpu(x) ((unsigned short)(x)) +#define cpu_to_be32(x) swab32((x)) +#define be32_to_cpu(x) swab32((x)) +#define cpu_to_be16(x) swab16((x)) +#define be16_to_cpu(x) swab16((x)) + +#define ntohl(x) be32_to_cpu(x) +#define htonl(x) cpu_to_be32(x) + +#endif /* _BYTEORDER_H */ diff --git a/src/arch/x86/include/arch/coreboot_tables.h b/src/arch/x86/include/arch/coreboot_tables.h new file mode 100644 index 0000000000..3c9bf98f22 --- /dev/null +++ b/src/arch/x86/include/arch/coreboot_tables.h @@ -0,0 +1,25 @@ +#ifndef COREBOOT_TABLE_H +#define COREBOOT_TABLE_H + +#include <boot/coreboot_tables.h> + +/* This file holds function prototypes for building the coreboot table. */ +unsigned long write_coreboot_table( + unsigned long low_table_start, unsigned long low_table_end, + unsigned long rom_table_start, unsigned long rom_table_end); + +void lb_memory_range(struct lb_memory *mem, + uint32_t type, uint64_t start, uint64_t size); + +/* Routines to extract part so the coreboot table or information + * from the coreboot table. + */ +struct lb_memory *get_lb_mem(void); + +extern struct cmos_option_table option_table; + +/* defined by mainboard.c if the mainboard requires extra resources */ +int add_mainboard_resources(struct lb_memory *mem); +int add_northbridge_resources(struct lb_memory *mem); + +#endif /* COREBOOT_TABLE_H */ diff --git a/src/arch/x86/include/arch/cpu.h b/src/arch/x86/include/arch/cpu.h new file mode 100644 index 0000000000..4d7be86223 --- /dev/null +++ b/src/arch/x86/include/arch/cpu.h @@ -0,0 +1,165 @@ +#ifndef ARCH_CPU_H +#define ARCH_CPU_H + +/* + * EFLAGS bits + */ +#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ +#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ +#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ +#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ +#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ +#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ +#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ +#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ +#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ +#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ +#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ +#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ +#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ +#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ +#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ +#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ +#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ + +struct cpuid_result { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +}; + +/* + * Generic CPUID function + */ +static inline struct cpuid_result cpuid(int op) +{ + struct cpuid_result result; + asm volatile( + "cpuid" + : "=a" (result.eax), + "=b" (result.ebx), + "=c" (result.ecx), + "=d" (result.edx) + : "0" (op)); + return result; +} + +/* + * CPUID functions returning a single datum + */ +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax; + + __asm__("cpuid" + : "=a" (eax) + : "0" (op) + : "ebx", "ecx", "edx"); + return eax; +} + +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx; + + __asm__("cpuid" + : "=a" (eax), "=b" (ebx) + : "0" (op) + : "ecx", "edx" ); + return ebx; +} + +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int eax, ecx; + + __asm__("cpuid" + : "=a" (eax), "=c" (ecx) + : "0" (op) + : "ebx", "edx" ); + return ecx; +} + +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx; + + __asm__("cpuid" + : "=a" (eax), "=d" (edx) + : "0" (op) + : "ebx", "ecx"); + return edx; +} + +#define X86_VENDOR_INVALID 0 +#define X86_VENDOR_INTEL 1 +#define X86_VENDOR_CYRIX 2 +#define X86_VENDOR_AMD 3 +#define X86_VENDOR_UMC 4 +#define X86_VENDOR_NEXGEN 5 +#define X86_VENDOR_CENTAUR 6 +#define X86_VENDOR_RISE 7 +#define X86_VENDOR_TRANSMETA 8 +#define X86_VENDOR_NSC 9 +#define X86_VENDOR_SIS 10 +#define X86_VENDOR_UNKNOWN 0xff + +#if !defined(__PRE_RAM__) +#include <device/device.h> + +struct cpu_device_id { + unsigned vendor; + unsigned device; +}; + +struct cpu_driver { + struct device_operations *ops; + struct cpu_device_id *id_table; +}; + +struct cpu_info { + device_t cpu; + unsigned long index; +}; + +static inline struct cpu_info *cpu_info(void) +{ + struct cpu_info *ci; + __asm__("andl %%esp,%0; " + "orl %2, %0 " + :"=r" (ci) + : "0" (~(CONFIG_STACK_SIZE - 1)), + "r" (CONFIG_STACK_SIZE - sizeof(struct cpu_info)) + ); + return ci; +} + +static inline unsigned long cpu_index(void) +{ + struct cpu_info *ci; + ci = cpu_info(); + return ci->index; +} + +struct cpuinfo_x86 { + uint8_t x86; /* CPU family */ + uint8_t x86_vendor; /* CPU vendor */ + uint8_t x86_model; + uint8_t x86_mask; +}; + +static void inline get_fms(struct cpuinfo_x86 *c, uint32_t tfms) +{ + c->x86 = (tfms >> 8) & 0xf; + c->x86_model = (tfms >> 4) & 0xf; + c->x86_mask = tfms & 0xf; + if (c->x86 == 0xf) + c->x86 += (tfms >> 20) & 0xff; + if (c->x86 >= 0x6) + c->x86_model += ((tfms >> 16) & 0xF) << 4; + +} +#endif + +#endif /* ARCH_CPU_H */ diff --git a/src/arch/x86/include/arch/hlt.h b/src/arch/x86/include/arch/hlt.h new file mode 100644 index 0000000000..ddfe169954 --- /dev/null +++ b/src/arch/x86/include/arch/hlt.h @@ -0,0 +1,16 @@ +#ifndef ARCH_HLT_H +#define ARCH_HLT_H + +#if defined(__ROMCC__) +static void hlt(void) +{ + __builtin_hlt(); +} +#else +static inline __attribute__((always_inline)) void hlt(void) +{ + asm("hlt"); +} +#endif + +#endif /* ARCH_HLT_H */ diff --git a/src/arch/x86/include/arch/interrupt.h b/src/arch/x86/include/arch/interrupt.h new file mode 100644 index 0000000000..2d2330b739 --- /dev/null +++ b/src/arch/x86/include/arch/interrupt.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 coresystems GmbH + * Copyright (C) 2009 Libra Li <libra.li@technexion.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "registers.h" + +/* setup interrupt handlers for mainboard */ +extern void mainboard_interrupt_handlers(int intXX, void *intXX_func); diff --git a/src/arch/x86/include/arch/io.h b/src/arch/x86/include/arch/io.h new file mode 100644 index 0000000000..aad84088d6 --- /dev/null +++ b/src/arch/x86/include/arch/io.h @@ -0,0 +1,168 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include <stdint.h> + +/* + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + */ +#if defined(__ROMCC__) +static inline void outb(uint8_t value, uint16_t port) +{ + __builtin_outb(value, port); +} + +static inline void outw(uint16_t value, uint16_t port) +{ + __builtin_outw(value, port); +} + +static inline void outl(uint32_t value, uint16_t port) +{ + __builtin_outl(value, port); +} + + +static inline uint8_t inb(uint16_t port) +{ + return __builtin_inb(port); +} + + +static inline uint16_t inw(uint16_t port) +{ + return __builtin_inw(port); +} + +static inline uint32_t inl(uint16_t port) +{ + return __builtin_inl(port); +} +#else +static inline void outb(uint8_t value, uint16_t port) +{ + __asm__ __volatile__ ("outb %b0, %w1" : : "a" (value), "Nd" (port)); +} + +static inline void outw(uint16_t value, uint16_t port) +{ + __asm__ __volatile__ ("outw %w0, %w1" : : "a" (value), "Nd" (port)); +} + +static inline void outl(uint32_t value, uint16_t port) +{ + __asm__ __volatile__ ("outl %0, %w1" : : "a" (value), "Nd" (port)); +} + +static inline uint8_t inb(uint16_t port) +{ + uint8_t value; + __asm__ __volatile__ ("inb %w1, %b0" : "=a"(value) : "Nd" (port)); + return value; +} + +static inline uint16_t inw(uint16_t port) +{ + uint16_t value; + __asm__ __volatile__ ("inw %w1, %w0" : "=a"(value) : "Nd" (port)); + return value; +} + +static inline uint32_t inl(uint16_t port) +{ + uint32_t value; + __asm__ __volatile__ ("inl %w1, %0" : "=a"(value) : "Nd" (port)); + return value; +} +#endif /* __ROMCC__ */ + +static inline void outsb(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsb " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void outsw(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsw " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void outsl(uint16_t port, const void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; outsl " + : "=S" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + + +static inline void insb(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insb " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void insw(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insw " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline void insl(uint16_t port, void *addr, unsigned long count) +{ + __asm__ __volatile__ ( + "cld ; rep ; insl " + : "=D" (addr), "=c" (count) + : "d"(port), "0"(addr), "1" (count) + ); +} + +static inline __attribute__((always_inline)) uint8_t read8(unsigned long addr) +{ + return *((volatile uint8_t *)(addr)); +} + +static inline __attribute__((always_inline)) uint16_t read16(unsigned long addr) +{ + return *((volatile uint16_t *)(addr)); +} + +static inline __attribute__((always_inline)) uint32_t read32(unsigned long addr) +{ + return *((volatile uint32_t *)(addr)); +} + +static inline __attribute__((always_inline)) void write8(unsigned long addr, uint8_t value) +{ + *((volatile uint8_t *)(addr)) = value; +} + +static inline __attribute__((always_inline)) void write16(unsigned long addr, uint16_t value) +{ + *((volatile uint16_t *)(addr)) = value; +} + +static inline __attribute__((always_inline)) void write32(unsigned long addr, uint32_t value) +{ + *((volatile uint32_t *)(addr)) = value; +} + +#endif + diff --git a/src/arch/x86/include/arch/ioapic.h b/src/arch/x86/include/arch/ioapic.h new file mode 100644 index 0000000000..623f617253 --- /dev/null +++ b/src/arch/x86/include/arch/ioapic.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __I386_ARCH_IOAPIC_H +#define __I386_ARCH_IOAPIC_H + +#define IO_APIC_ADDR 0xfec00000UL +#define IO_APIC_INTERRUPTS 24 + +#define ALL (0xff << 24) +#define NONE (0) +#define DISABLED (1 << 16) +#define ENABLED (0 << 16) +#define TRIGGER_EDGE (0 << 15) +#define TRIGGER_LEVEL (1 << 15) +#define POLARITY_HIGH (0 << 13) +#define POLARITY_LOW (1 << 13) +#define PHYSICAL_DEST (0 << 11) +#define LOGICAL_DEST (1 << 11) +#define ExtINT (7 << 8) +#define NMI (4 << 8) +#define SMI (2 << 8) +#define INT (1 << 8) + +void setup_ioapic(u32 ioapic_base, u8 ioapic_id); +void clear_ioapic(u32 ioapic_base); + +#endif diff --git a/src/arch/x86/include/arch/llshell.h b/src/arch/x86/include/arch/llshell.h new file mode 100644 index 0000000000..556df7d046 --- /dev/null +++ b/src/arch/x86/include/arch/llshell.h @@ -0,0 +1,11 @@ +#ifndef __ARCH_LLSHELL__ +#define __ARCH_LLSHELL__ + + +#if CONFIG_LLSHELL +#define llshell() asm("jmp low_level_shell"); +#else +#define llshell() print_debug("LLSHELL not active.\n"); +#endif + +#endif diff --git a/src/arch/x86/include/arch/mmio_conf.h b/src/arch/x86/include/arch/mmio_conf.h new file mode 100644 index 0000000000..08962f02fa --- /dev/null +++ b/src/arch/x86/include/arch/mmio_conf.h @@ -0,0 +1,67 @@ +#ifndef ARCH_MMIO_H +#define ARCH_MMIO_H 1 + + +// Extended read, constrain to use registers as mandated by AMD MMCONFIG mechanism. + +static inline __attribute__((always_inline)) uint8_t read8x(uint32_t addr) +{ + uint8_t value; + __asm__ volatile ( + "movb (%1), %%al\n\t" + :"=a"(value): "b" (addr) + ); + return value; +} + +static inline __attribute__((always_inline)) uint16_t read16x(uint32_t addr) +{ + uint16_t value; + __asm__ volatile ( + "movw (%1), %%ax\n\t" + :"=a"(value): "b" (addr) + ); + + return value; + +} + +static inline __attribute__((always_inline)) uint32_t read32x(uint32_t addr) +{ + uint32_t value; + __asm__ volatile ( + "movl (%1), %%eax\n\t" + :"=a"(value): "b" (addr) + ); + + return value; + +} + +static inline __attribute__((always_inline)) void write8x(uint32_t addr, uint8_t value) +{ + __asm__ volatile ( + "movb %%al, (%0)\n\t" + :: "b" (addr), "a" (value) + ); + +} + +static inline __attribute__((always_inline)) void write16x(uint32_t addr, uint16_t value) +{ + __asm__ volatile ( + "movw %%ax, (%0)\n\t" + :: "b" (addr), "a" (value) + ); + +} + +static inline __attribute__((always_inline)) void write32x(uint32_t addr, uint32_t value) +{ + __asm__ volatile ( + "movl %%eax, (%0)\n\t" + :: "b" (addr), "a" (value) + ); +} + +#endif /* ARCH_MMIO_H */ diff --git a/src/arch/x86/include/arch/pci_ops.h b/src/arch/x86/include/arch/pci_ops.h new file mode 100644 index 0000000000..9c4e029b24 --- /dev/null +++ b/src/arch/x86/include/arch/pci_ops.h @@ -0,0 +1,13 @@ +#ifndef ARCH_I386_PCI_OPS_H +#define ARCH_I386_PCI_OPS_H + +extern const struct pci_bus_operations pci_cf8_conf1; +extern const struct pci_bus_operations pci_cf8_conf2; + +#if CONFIG_MMCONF_SUPPORT==1 +extern const struct pci_bus_operations pci_ops_mmconf; +#endif + +void pci_set_method(device_t dev); + +#endif /* ARCH_I386_PCI_OPS_H */ diff --git a/src/arch/x86/include/arch/pciconf.h b/src/arch/x86/include/arch/pciconf.h new file mode 100644 index 0000000000..a35693519e --- /dev/null +++ b/src/arch/x86/include/arch/pciconf.h @@ -0,0 +1,14 @@ +#ifndef PCI_CONF_REG_INDEX + +// These are defined in the PCI spec, and hence are theoretically +// inclusive of ANYTHING that uses a PCI bus. +#define PCI_CONF_REG_INDEX 0xcf8 +#define PCI_CONF_REG_DATA 0xcfc + +#if CONFIG_PCI_IO_CFG_EXT == 0 +#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where)) +#else +#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where & 0xff) | ((where & 0xf00)<<16) ) +#endif + +#endif diff --git a/src/arch/x86/include/arch/pirq_routing.h b/src/arch/x86/include/arch/pirq_routing.h new file mode 100644 index 0000000000..0b65eac29b --- /dev/null +++ b/src/arch/x86/include/arch/pirq_routing.h @@ -0,0 +1,54 @@ +#ifndef ARCH_PIRQ_ROUTING_H +#define ARCH_PIRQ_ROUTING_H + +#if CONFIG_GENERATE_PIRQ_TABLE==1 +#include <stdint.h> + +#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) +#define PIRQ_VERSION 0x0100 + +struct irq_info { + u8 bus, devfn; /* Bus, device and function */ + struct { + u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ + u16 bitmap; /* Available IRQs */ + } __attribute__((packed)) irq[4]; + u8 slot; /* Slot number, 0=onboard */ + u8 rfu; +} __attribute__((packed)); + +#ifndef CONFIG_IRQ_SLOT_COUNT +#warning "IRQ_SLOT_COUNT is not defined in Kconfig. PIRQ won't work correctly." +#endif + +struct irq_routing_table { + u32 signature; /* PIRQ_SIGNATURE should be here */ + u16 version; /* PIRQ_VERSION */ + u16 size; /* Table size in bytes */ + u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ + u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ + u16 rtr_vendor, rtr_device;/* Vendor/device ID of interrupt router */ + u32 miniport_data; + u8 rfu[11]; + u8 checksum; /* Modulo 256 checksum must give zero */ + struct irq_info slots[CONFIG_IRQ_SLOT_COUNT]; +} __attribute__((packed)); + +extern const struct irq_routing_table intel_irq_routing_table; + +unsigned long copy_pirq_routing_table(unsigned long start); +unsigned long write_pirq_routing_table(unsigned long start); + +#if CONFIG_PIRQ_ROUTE==1 +void pirq_routing_irqs(unsigned long start); +void pirq_assign_irqs(const unsigned char pIntAtoD[4]); +#else +#define pirq_routing_irqs(start) {} +#endif + +#else +#define copy_pirq_routing_table(start) (start) +#define write_pirq_routing_table(start) (start) +#endif + +#endif /* ARCH_PIRQ_ROUTING_H */ diff --git a/src/arch/x86/include/arch/registers.h b/src/arch/x86/include/arch/registers.h new file mode 100644 index 0000000000..bc1b681339 --- /dev/null +++ b/src/arch/x86/include/arch/registers.h @@ -0,0 +1,32 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2009 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_REGISTERS_H +#define __ARCH_REGISTERS_H + +struct eregs { + uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi; + uint32_t vector; + uint32_t error_code; + uint32_t eip; + uint32_t cs; + uint32_t eflags; +}; + +#endif diff --git a/src/arch/x86/include/arch/rom_segs.h b/src/arch/x86/include/arch/rom_segs.h new file mode 100644 index 0000000000..8c00eb3b7a --- /dev/null +++ b/src/arch/x86/include/arch/rom_segs.h @@ -0,0 +1,7 @@ +#ifndef ROM_SEGS_H +#define ROM_SEGS_H + +#define ROM_CODE_SEG 0x08 +#define ROM_DATA_SEG 0x10 + +#endif /* ROM_SEGS_H */ diff --git a/src/arch/x86/include/arch/romcc_io.h b/src/arch/x86/include/arch/romcc_io.h new file mode 100644 index 0000000000..79ea26550e --- /dev/null +++ b/src/arch/x86/include/arch/romcc_io.h @@ -0,0 +1,341 @@ +#ifndef ARCH_ROMCC_IO_H +#define ARCH_ROMCC_IO_H 1 + +#include <stdint.h> + +// arch/io.h is pulled in in many places but it could +// also be pulled in here for all romcc/romstage code. +// #include <arch/io.h> + +#if CONFIG_MMCONF_SUPPORT + +#include <arch/mmio_conf.h> + +#endif + +static inline int log2(int value) +{ + unsigned int r = 0; + __asm__ volatile ( + "bsrl %1, %0\n\t" + "jnz 1f\n\t" + "movl $-1, %0\n\t" + "1:\n\t" + : "=r" (r) : "r" (value)); + return r; + +} +static inline int log2f(int value) +{ + unsigned int r = 0; + __asm__ volatile ( + "bsfl %1, %0\n\t" + "jnz 1f\n\t" + "movl $-1, %0\n\t" + "1:\n\t" + : "=r" (r) : "r" (value)); + return r; + +} + +#define PCI_ADDR(SEGBUS, DEV, FN, WHERE) ( \ + (((SEGBUS) & 0xFFF) << 20) | \ + (((DEV) & 0x1F) << 15) | \ + (((FN) & 0x07) << 12) | \ + ((WHERE) & 0xFFF)) + +#define PCI_DEV(SEGBUS, DEV, FN) ( \ + (((SEGBUS) & 0xFFF) << 20) | \ + (((DEV) & 0x1F) << 15) | \ + (((FN) & 0x07) << 12)) + +#define PCI_ID(VENDOR_ID, DEVICE_ID) \ + ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF)) + + +#define PNP_DEV(PORT, FUNC) (((PORT) << 8) | (FUNC)) + +typedef unsigned device_t; /* pci and pci_mmio need to have different ways to have dev */ + +/* FIXME: We need to make the coreboot to run at 64bit mode, So when read/write memory above 4G, + * We don't need to set %fs, and %gs anymore + * Before that We need to use %gs, and leave %fs to other RAM access + */ + +static inline __attribute__((always_inline)) uint8_t pci_io_read_config8(device_t dev, unsigned where) +{ + unsigned addr; +#if CONFIG_PCI_IO_CFG_EXT == 0 + addr = (dev>>4) | where; +#else + addr = (dev>>4) | (where & 0xff) | ((where & 0xf00)<<16); //seg == 0 +#endif + outl(0x80000000 | (addr & ~3), 0xCF8); + return inb(0xCFC + (addr & 3)); +} + +#if CONFIG_MMCONF_SUPPORT +static inline __attribute__((always_inline)) uint8_t pci_mmio_read_config8(device_t dev, unsigned where) +{ + unsigned addr; + addr = CONFIG_MMCONF_BASE_ADDRESS | dev | where; + return read8x(addr); +} +#endif +static inline __attribute__((always_inline)) uint8_t pci_read_config8(device_t dev, unsigned where) +{ +#if CONFIG_MMCONF_SUPPORT_DEFAULT + return pci_mmio_read_config8(dev, where); +#else + return pci_io_read_config8(dev, where); +#endif +} + +static inline __attribute__((always_inline)) uint16_t pci_io_read_config16(device_t dev, unsigned where) +{ + unsigned addr; +#if CONFIG_PCI_IO_CFG_EXT == 0 + addr = (dev>>4) | where; +#else + addr = (dev>>4) | (where & 0xff) | ((where & 0xf00)<<16); +#endif + outl(0x80000000 | (addr & ~3), 0xCF8); + return inw(0xCFC + (addr & 2)); +} + +#if CONFIG_MMCONF_SUPPORT +static inline __attribute__((always_inline)) uint16_t pci_mmio_read_config16(device_t dev, unsigned where) +{ + unsigned addr; + addr = CONFIG_MMCONF_BASE_ADDRESS | dev | (where & ~1); + return read16x(addr); +} +#endif + +static inline __attribute__((always_inline)) uint16_t pci_read_config16(device_t dev, unsigned where) +{ +#if CONFIG_MMCONF_SUPPORT_DEFAULT + return pci_mmio_read_config16(dev, where); +#else + return pci_io_read_config16(dev, where); +#endif +} + + +static inline __attribute__((always_inline)) uint32_t pci_io_read_config32(device_t dev, unsigned where) +{ + unsigned addr; +#if CONFIG_PCI_IO_CFG_EXT == 0 + addr = (dev>>4) | where; +#else + addr = (dev>>4) | (where & 0xff) | ((where & 0xf00)<<16); +#endif + outl(0x80000000 | (addr & ~3), 0xCF8); + return inl(0xCFC); +} + +#if CONFIG_MMCONF_SUPPORT +static inline __attribute__((always_inline)) uint32_t pci_mmio_read_config32(device_t dev, unsigned where) +{ + unsigned addr; + addr = CONFIG_MMCONF_BASE_ADDRESS | dev | (where & ~3); + return read32x(addr); +} +#endif + +static inline __attribute__((always_inline)) uint32_t pci_read_config32(device_t dev, unsigned where) +{ +#if CONFIG_MMCONF_SUPPORT_DEFAULT + return pci_mmio_read_config32(dev, where); +#else + return pci_io_read_config32(dev, where); +#endif +} + +static inline __attribute__((always_inline)) void pci_io_write_config8(device_t dev, unsigned where, uint8_t value) +{ + unsigned addr; +#if CONFIG_PCI_IO_CFG_EXT == 0 + addr = (dev>>4) | where; +#else + addr = (dev>>4) | (where & 0xff) | ((where & 0xf00)<<16); +#endif + outl(0x80000000 | (addr & ~3), 0xCF8); + outb(value, 0xCFC + (addr & 3)); +} + +#if CONFIG_MMCONF_SUPPORT +static inline __attribute__((always_inline)) void pci_mmio_write_config8(device_t dev, unsigned where, uint8_t value) +{ + unsigned addr; + addr = CONFIG_MMCONF_BASE_ADDRESS | dev | where; + write8x(addr, value); +} +#endif + +static inline __attribute__((always_inline)) void pci_write_config8(device_t dev, unsigned where, uint8_t value) +{ +#if CONFIG_MMCONF_SUPPORT_DEFAULT + pci_mmio_write_config8(dev, where, value); +#else + pci_io_write_config8(dev, where, value); +#endif +} + + +static inline __attribute__((always_inline)) void pci_io_write_config16(device_t dev, unsigned where, uint16_t value) +{ + unsigned addr; +#if CONFIG_PCI_IO_CFG_EXT == 0 + addr = (dev>>4) | where; +#else + addr = (dev>>4) | (where & 0xff) | ((where & 0xf00)<<16); +#endif + outl(0x80000000 | (addr & ~3), 0xCF8); + outw(value, 0xCFC + (addr & 2)); +} + +#if CONFIG_MMCONF_SUPPORT +static inline __attribute__((always_inline)) void pci_mmio_write_config16(device_t dev, unsigned where, uint16_t value) +{ + unsigned addr; + addr = CONFIG_MMCONF_BASE_ADDRESS | dev | (where & ~1); + write16x(addr, value); +} +#endif + +static inline __attribute__((always_inline)) void pci_write_config16(device_t dev, unsigned where, uint16_t value) +{ +#if CONFIG_MMCONF_SUPPORT_DEFAULT + pci_mmio_write_config16(dev, where, value); +#else + pci_io_write_config16(dev, where, value); +#endif +} + + +static inline __attribute__((always_inline)) void pci_io_write_config32(device_t dev, unsigned where, uint32_t value) +{ + unsigned addr; +#if CONFIG_PCI_IO_CFG_EXT == 0 + addr = (dev>>4) | where; +#else + addr = (dev>>4) | (where & 0xff) | ((where & 0xf00)<<16); +#endif + outl(0x80000000 | (addr & ~3), 0xCF8); + outl(value, 0xCFC); +} + +#if CONFIG_MMCONF_SUPPORT +static inline __attribute__((always_inline)) void pci_mmio_write_config32(device_t dev, unsigned where, uint32_t value) +{ + unsigned addr; + addr = CONFIG_MMCONF_BASE_ADDRESS | dev | (where & ~3); + write32x(addr, value); +} +#endif + +static inline __attribute__((always_inline)) void pci_write_config32(device_t dev, unsigned where, uint32_t value) +{ +#if CONFIG_MMCONF_SUPPORT_DEFAULT + pci_mmio_write_config32(dev, where, value); +#else + pci_io_write_config32(dev, where, value); +#endif +} + +#define PCI_DEV_INVALID (0xffffffffU) +static inline device_t pci_io_locate_device(unsigned pci_id, device_t dev) +{ + for(; dev <= PCI_DEV(255, 31, 7); dev += PCI_DEV(0,0,1)) { + unsigned int id; + id = pci_io_read_config32(dev, 0); + if (id == pci_id) { + return dev; + } + } + return PCI_DEV_INVALID; +} + +static inline device_t pci_locate_device(unsigned pci_id, device_t dev) +{ + for(; dev <= PCI_DEV(255|(((1<<CONFIG_PCI_BUS_SEGN_BITS)-1)<<8), 31, 7); dev += PCI_DEV(0,0,1)) { + unsigned int id; + id = pci_read_config32(dev, 0); + if (id == pci_id) { + return dev; + } + } + return PCI_DEV_INVALID; +} + +static inline device_t pci_locate_device_on_bus(unsigned pci_id, unsigned bus) +{ + device_t dev, last; + + dev = PCI_DEV(bus, 0, 0); + last = PCI_DEV(bus, 31, 7); + + for(; dev <=last; dev += PCI_DEV(0,0,1)) { + unsigned int id; + id = pci_read_config32(dev, 0); + if (id == pci_id) { + return dev; + } + } + return PCI_DEV_INVALID; +} + +/* Generic functions for pnp devices */ +static inline __attribute__((always_inline)) void pnp_write_config(device_t dev, uint8_t reg, uint8_t value) +{ + unsigned port = dev >> 8; + outb(reg, port ); + outb(value, port +1); +} + +static inline __attribute__((always_inline)) uint8_t pnp_read_config(device_t dev, uint8_t reg) +{ + unsigned port = dev >> 8; + outb(reg, port); + return inb(port +1); +} + +static inline __attribute__((always_inline)) void pnp_set_logical_device(device_t dev) +{ + unsigned device = dev & 0xff; + pnp_write_config(dev, 0x07, device); +} + +static inline __attribute__((always_inline)) void pnp_set_enable(device_t dev, int enable) +{ + pnp_write_config(dev, 0x30, enable?0x1:0x0); +} + +static inline __attribute__((always_inline)) int pnp_read_enable(device_t dev) +{ + return !!pnp_read_config(dev, 0x30); +} + +static inline __attribute__((always_inline)) void pnp_set_iobase(device_t dev, unsigned index, unsigned iobase) +{ + pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff); + pnp_write_config(dev, index + 1, iobase & 0xff); +} + +static inline __attribute__((always_inline)) uint16_t pnp_read_iobase(device_t dev, unsigned index) +{ + return ((uint16_t)(pnp_read_config(dev, index)) << 8) | pnp_read_config(dev, index + 1); +} + +static inline __attribute__((always_inline)) void pnp_set_irq(device_t dev, unsigned index, unsigned irq) +{ + pnp_write_config(dev, index, irq); +} + +static inline __attribute__((always_inline)) void pnp_set_drq(device_t dev, unsigned index, unsigned drq) +{ + pnp_write_config(dev, index, drq & 0xff); +} + +#endif /* ARCH_ROMCC_IO_H */ diff --git a/src/arch/x86/include/arch/smp/atomic.h b/src/arch/x86/include/arch/smp/atomic.h new file mode 100644 index 0000000000..18bbae27cb --- /dev/null +++ b/src/arch/x86/include/arch/smp/atomic.h @@ -0,0 +1,69 @@ +#ifndef ARCH_SMP_ATOMIC_H +#define ARCH_SMP_ATOMIC_H + +/* + * Make sure gcc doesn't try to be clever and move things around + * on us. We need to use _exactly_ the address the user gave us, + * not some alias that contains the same information. + */ +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + */ + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_read(v) ((v)->counter) + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_set(v,i) (((v)->counter) = (i)) + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ __attribute__((always_inline)) void atomic_inc(atomic_t *v) +{ + __asm__ __volatile__( + "lock ; incl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ __attribute__((always_inline)) void atomic_dec(atomic_t *v) +{ + __asm__ __volatile__( + "lock ; decl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + + + +#endif /* ARCH_SMP_ATOMIC_H */ diff --git a/src/arch/x86/include/arch/smp/mpspec.h b/src/arch/x86/include/arch/smp/mpspec.h new file mode 100644 index 0000000000..bc09f485d8 --- /dev/null +++ b/src/arch/x86/include/arch/smp/mpspec.h @@ -0,0 +1,281 @@ +#ifndef __ASM_MPSPEC_H +#define __ASM_MPSPEC_H + +#include <device/device.h> +/* + * Structure definitions for SMP machines following the + * Intel Multiprocessing Specification 1.1 and 1.4. + */ + +/* + * This tag identifies where the SMP configuration + * information is. + */ + +#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') + +/* + * a maximum of 16 APICs with the current APIC ID architecture. + */ +#define MAX_APICS 16 + + +#define SMP_FLOATING_TABLE_LEN sizeof(struct intel_mp_floating) + +struct intel_mp_floating +{ + char mpf_signature[4]; /* "_MP_" */ + unsigned long mpf_physptr; /* Configuration table address */ + unsigned char mpf_length; /* Our length (paragraphs) */ + unsigned char mpf_specification;/* Specification version */ + unsigned char mpf_checksum; /* Checksum (makes sum 0) */ + unsigned char mpf_feature1; /* Standard or configuration ? */ + unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */ +#define MP_FEATURE_VIRTUALWIRE (1 << 7) +#define MP_FEATURE_PIC (0 << 7) + unsigned char mpf_feature3; /* Unused (0) */ + unsigned char mpf_feature4; /* Unused (0) */ + unsigned char mpf_feature5; /* Unused (0) */ +} __attribute__((packed)); + +struct mp_config_table +{ + char mpc_signature[4]; +#define MPC_SIGNATURE "PCMP" + unsigned short mpc_length; /* Size of table */ + char mpc_spec; /* 0x01 */ + char mpc_checksum; + char mpc_oem[8]; + char mpc_productid[12]; + unsigned long mpc_oemptr; /* 0 if not present */ + unsigned short mpc_oemsize; /* 0 if not present */ + unsigned short mpc_entry_count; + unsigned long mpc_lapic; /* APIC address */ + unsigned short mpe_length; /* Extended Table size */ + unsigned char mpe_checksum; /* Extended Table checksum */ + unsigned char reserved; +} __attribute__((packed)); + +/* Followed by entries */ + +#define MP_PROCESSOR 0 +#define MP_BUS 1 +#define MP_IOAPIC 2 +#define MP_INTSRC 3 +#define MP_LINTSRC 4 + +struct mpc_config_processor +{ + unsigned char mpc_type; + unsigned char mpc_apicid; /* Local APIC number */ + unsigned char mpc_apicver; /* Its versions */ + unsigned char mpc_cpuflag; +#define MPC_CPU_ENABLED 1 /* Processor is available */ +#define MPC_CPU_BOOTPROCESSOR 2 /* Processor is the BP */ + unsigned long mpc_cpufeature; +#define MPC_CPU_STEPPING_MASK 0x0F +#define MPC_CPU_MODEL_MASK 0xF0 +#define MPC_CPU_FAMILY_MASK 0xF00 + unsigned long mpc_featureflag; /* CPUID feature value */ + unsigned long mpc_reserved[2]; +} __attribute__((packed)); + +struct mpc_config_bus +{ + unsigned char mpc_type; + unsigned char mpc_busid; + unsigned char mpc_bustype[6]; +} __attribute__((packed)); + +#define BUSTYPE_EISA "EISA" +#define BUSTYPE_ISA "ISA" +#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ +#define BUSTYPE_MCA "MCA" +#define BUSTYPE_VL "VL" /* Local bus */ +#define BUSTYPE_PCI "PCI" +#define BUSTYPE_PCMCIA "PCMCIA" + +struct mpc_config_ioapic +{ + unsigned char mpc_type; + unsigned char mpc_apicid; + unsigned char mpc_apicver; + unsigned char mpc_flags; +#define MPC_APIC_USABLE 0x01 + unsigned long mpc_apicaddr; +} __attribute__((packed)); + +struct mpc_config_intsrc +{ + unsigned char mpc_type; + unsigned char mpc_irqtype; + unsigned short mpc_irqflag; + unsigned char mpc_srcbus; + unsigned char mpc_srcbusirq; + unsigned char mpc_dstapic; + unsigned char mpc_dstirq; +} __attribute__((packed)); + +enum mp_irq_source_types { + mp_INT = 0, + mp_NMI = 1, + mp_SMI = 2, + mp_ExtINT = 3 +}; + +#define MP_IRQ_POLARITY_DEFAULT 0x0 +#define MP_IRQ_POLARITY_HIGH 0x1 +#define MP_IRQ_POLARITY_LOW 0x3 +#define MP_IRQ_POLARITY_MASK 0x3 +#define MP_IRQ_TRIGGER_DEFAULT 0x0 +#define MP_IRQ_TRIGGER_EDGE 0x4 +#define MP_IRQ_TRIGGER_LEVEL 0xc +#define MP_IRQ_TRIGGER_MASK 0xc + + +struct mpc_config_lintsrc +{ + unsigned char mpc_type; + unsigned char mpc_irqtype; + unsigned short mpc_irqflag; + unsigned char mpc_srcbusid; + unsigned char mpc_srcbusirq; + unsigned char mpc_destapic; +#define MP_APIC_ALL 0xFF + unsigned char mpc_destapiclint; +} __attribute__((packed)); + +/* + * Default configurations + * + * 1 2 CPU ISA 82489DX + * 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining + * 3 2 CPU EISA 82489DX + * 4 2 CPU MCA 82489DX + * 5 2 CPU ISA+PCI + * 6 2 CPU EISA+PCI + * 7 2 CPU MCA+PCI + */ + +#define MAX_IRQ_SOURCES 128 +#define MAX_MP_BUSSES 32 +enum mp_bustype { + MP_BUS_ISA, + MP_BUS_EISA, + MP_BUS_PCI, + MP_BUS_MCA +}; + +/* Followed by entries */ + +#define MPE_SYSTEM_ADDRESS_SPACE 0x80 +#define MPE_BUS_HIERARCHY 0x81 +#define MPE_COMPATIBILITY_ADDRESS_SPACE 0x82 + +struct mp_exten_config { + unsigned char mpe_type; + unsigned char mpe_length; +} __attribute__((packed)); + +typedef struct mp_exten_config *mpe_t; + +struct mp_exten_system_address_space { + unsigned char mpe_type; + unsigned char mpe_length; + unsigned char mpe_busid; + unsigned char mpe_address_type; +#define ADDRESS_TYPE_IO 0 +#define ADDRESS_TYPE_MEM 1 +#define ADDRESS_TYPE_PREFETCH 2 + unsigned int mpe_address_base_low; + unsigned int mpe_address_base_high; + unsigned int mpe_address_length_low; + unsigned int mpe_address_length_high; +} __attribute__((packed)); + +struct mp_exten_bus_hierarchy { + unsigned char mpe_type; + unsigned char mpe_length; + unsigned char mpe_busid; + unsigned char mpe_bus_info; +#define BUS_SUBTRACTIVE_DECODE 1 + unsigned char mpe_parent_busid; + unsigned char reserved[3]; +} __attribute__((packed)); + +struct mp_exten_compatibility_address_space { + unsigned char mpe_type; + unsigned char mpe_length; + unsigned char mpe_busid; + unsigned char mpe_address_modifier; +#define ADDRESS_RANGE_SUBTRACT 1 +#define ADDRESS_RANGE_ADD 0 + unsigned int mpe_range_list; +#define RANGE_LIST_IO_ISA 0 + /* X100 - X3FF + * X500 - X7FF + * X900 - XBFF + * XD00 - XFFF + */ +#define RANGE_LIST_IO_VGA 1 + /* X3B0 - X3BB + * X3C0 - X3DF + * X7B0 - X7BB + * X7C0 - X7DF + * XBB0 - XBBB + * XBC0 - XBDF + * XFB0 - XFBB + * XFC0 - XCDF + */ +} __attribute__((packed)); + +/* Default local apic addr */ +#define LAPIC_ADDR 0xFEE00000 + +void mptable_init(struct mp_config_table *mc, const char *productid, + u32 lapic_addr); + +void *smp_next_mpc_entry(struct mp_config_table *mc); +void *smp_next_mpe_entry(struct mp_config_table *mc); + +void smp_write_processor(struct mp_config_table *mc, + unsigned char apicid, unsigned char apicver, + unsigned char cpuflag, unsigned int cpufeature, + unsigned int featureflag); +void smp_write_processors(struct mp_config_table *mc); +void smp_write_ioapic(struct mp_config_table *mc, + unsigned char id, unsigned char ver, + unsigned long apicaddr); +void smp_write_intsrc(struct mp_config_table *mc, + unsigned char irqtype, unsigned short irqflag, + unsigned char srcbus, unsigned char srcbusirq, + unsigned char dstapic, unsigned char dstirq); +void smp_write_intsrc_pci_bridge(struct mp_config_table *mc, + unsigned char irqtype, unsigned short irqflag, + struct device *dev, + unsigned char dstapic, unsigned char *dstirq); +void smp_write_lintsrc(struct mp_config_table *mc, + unsigned char irqtype, unsigned short irqflag, + unsigned char srcbusid, unsigned char srcbusirq, + unsigned char destapic, unsigned char destapiclint); +void smp_write_address_space(struct mp_config_table *mc, + unsigned char busid, unsigned char address_type, + unsigned int address_base_low, unsigned int address_base_high, + unsigned int address_length_low, unsigned int address_length_high); +void smp_write_bus_hierarchy(struct mp_config_table *mc, + unsigned char busid, unsigned char bus_info, + unsigned char parent_busid); +void smp_write_compatibility_address_space(struct mp_config_table *mc, + unsigned char busid, unsigned char address_modifier, + unsigned int range_list); +unsigned char smp_compute_checksum(void *v, int len); +void *smp_write_floating_table(unsigned long addr); +void *smp_write_floating_table_physaddr(unsigned long addr, + unsigned long mpf_physptr); +unsigned long write_smp_table(unsigned long addr); + +void mptable_add_isa_interrupts(struct mp_config_table *mc, unsigned long bus_isa, unsigned long apicid, int external); +void mptable_write_buses(struct mp_config_table *mc, int *max_pci_bus, int *isa_bus); + +#endif + diff --git a/src/arch/x86/include/arch/smp/spinlock.h b/src/arch/x86/include/arch/smp/spinlock.h new file mode 100644 index 0000000000..5c1dd94c36 --- /dev/null +++ b/src/arch/x86/include/arch/smp/spinlock.h @@ -0,0 +1,64 @@ +#ifndef ARCH_SMP_SPINLOCK_H +#define ARCH_SMP_SPINLOCK_H + +/* + * Your basic SMP spinlocks, allowing only a single CPU anywhere + */ + +typedef struct { + volatile unsigned int lock; +} spinlock_t; + + +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 } +#define DECLARE_SPIN_LOCK(x) static spinlock_t x = SPIN_LOCK_UNLOCKED; + +/* + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * We make no fairness assumptions. They have a cost. + */ +#define barrier() __asm__ __volatile__("": : :"memory") +#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0) +#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) + +#define spin_lock_string \ + "\n1:\t" \ + "lock ; decb %0\n\t" \ + "js 2f\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\t" \ + "cmpb $0,%0\n\t" \ + "rep;nop\n\t" \ + "jle 2b\n\t" \ + "jmp 1b\n" \ + ".previous" + +/* + * This works. Despite all the confusion. + */ +#define spin_unlock_string \ + "movb $1,%0" + +static inline __attribute__((always_inline)) void spin_lock(spinlock_t *lock) +{ + __asm__ __volatile__( + spin_lock_string + :"=m" (lock->lock) : : "memory"); +} + +static inline __attribute__((always_inline)) void spin_unlock(spinlock_t *lock) +{ + __asm__ __volatile__( + spin_unlock_string + :"=m" (lock->lock) : : "memory"); +} + +/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ +static inline __attribute__((always_inline)) void cpu_relax(void) +{ + __asm__ __volatile__("rep;nop": : :"memory"); +} + +#endif /* ARCH_SMP_SPINLOCK_H */ diff --git a/src/arch/x86/include/arch/stages.h b/src/arch/x86/include/arch/stages.h new file mode 100644 index 0000000000..00d2a93ea3 --- /dev/null +++ b/src/arch/x86/include/arch/stages.h @@ -0,0 +1,25 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2010 coresystems GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_STAGES_H +#define __ARCH_STAGES_H +void cbfs_and_run_core(const char *filename, unsigned int ebp); +void __attribute__((regparm(0))) copy_and_run(unsigned cpu_reset); +void __attribute__((regparm(0))) copy_and_run_ap_code_in_car(unsigned ret_addr); +#endif diff --git a/src/arch/x86/include/bitops.h b/src/arch/x86/include/bitops.h new file mode 100644 index 0000000000..9206465c77 --- /dev/null +++ b/src/arch/x86/include/bitops.h @@ -0,0 +1,20 @@ +#ifndef I386_BITOPS_H +#define I386_BITOPS_H + +/** + * log2 - Find the truncated log base 2 of x + */ + +static inline unsigned long log2(unsigned long x) +{ + unsigned long r = 0; + __asm__( + "bsrl %1, %0\n\t" + "jnz 1f\n\t" + "movl $-1, %0\n\t" + "1:\n\t" + : "=r" (r) : "r" (x)); + return r; + +} +#endif /* I386_BITOPS_H */ diff --git a/src/arch/x86/include/bootblock_common.h b/src/arch/x86/include/bootblock_common.h new file mode 100644 index 0000000000..895a185c6f --- /dev/null +++ b/src/arch/x86/include/bootblock_common.h @@ -0,0 +1,33 @@ +#define __PRE_RAM__ +#if CONFIG_LOGICAL_CPUS && \ + (defined(CONFIG_BOOTBLOCK_NORTHBRIDGE_INIT) || defined(CONFIG_BOOTBLOCK_SOUTHBRIDGE_INIT)) +#include <cpu/x86/lapic/boot_cpu.c> +#else +#define boot_cpu(x) 1 +#endif + +#ifdef CONFIG_BOOTBLOCK_NORTHBRIDGE_INIT +#include CONFIG_BOOTBLOCK_NORTHBRIDGE_INIT +#else +static void bootblock_northbridge_init(void) { } +#endif +#ifdef CONFIG_BOOTBLOCK_SOUTHBRIDGE_INIT +#include CONFIG_BOOTBLOCK_SOUTHBRIDGE_INIT +#else +static void bootblock_southbridge_init(void) { } +#endif + +static unsigned long findstage(char* target) +{ + unsigned long entry; + asm volatile ( + "mov $1f, %%esp\n\t" + "jmp walkcbfs\n\t" + "1:\n\t" : "=a" (entry) : "S" (target) : "ebx", "ecx", "edi", "esp"); + return entry; +} + +static void call(unsigned long addr, unsigned long bist) +{ + asm volatile ("jmp *%0\n\t" : : "r" (addr), "a" (bist)); +} diff --git a/src/arch/x86/include/div64.h b/src/arch/x86/include/div64.h new file mode 100644 index 0000000000..3634f6dd14 --- /dev/null +++ b/src/arch/x86/include/div64.h @@ -0,0 +1,51 @@ +#ifndef __I386_DIV64 +#define __I386_DIV64 + +/* + * do_div() is NOT a C function. It wants to return + * two values (the quotient and the remainder), but + * since that doesn't work very well in C, what it + * does is: + * + * - modifies the 64-bit dividend _in_place_ + * - returns the 32-bit remainder + * + * This ends up being the most efficient "calling + * convention" on x86. + */ +#define do_div(n,base) ({ \ + unsigned long __upper, __low, __high, __mod, __base; \ + __base = (base); \ + asm("":"=a" (__low), "=d" (__high):"A" (n)); \ + __upper = __high; \ + if (__high) { \ + __upper = __high % (__base); \ + __high = __high / (__base); \ + } \ + asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \ + asm("":"=A" (n):"a" (__low),"d" (__high)); \ + __mod; \ +}) + +/* + * (long)X = ((long long)divs) / (long)div + * (long)rem = ((long long)divs) % (long)div + * + * Warning, this will do an exception if X overflows. + */ +#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c) + +extern inline long +div_ll_X_l_rem(long long divs, long div, long *rem); + +extern inline long +div_ll_X_l_rem(long long divs, long div, long *rem) +{ + long dum2; + __asm__("divl %2":"=a"(dum2), "=d"(*rem) + : "rm"(div), "A"(divs)); + + return dum2; + +} +#endif diff --git a/src/arch/x86/include/stddef.h b/src/arch/x86/include/stddef.h new file mode 100644 index 0000000000..e4fc019c87 --- /dev/null +++ b/src/arch/x86/include/stddef.h @@ -0,0 +1,15 @@ +#ifndef I386_STDDEF_H +#define I386_STDDEF_H + +typedef long ptrdiff_t; +typedef unsigned long size_t; +typedef long ssize_t; + +typedef int wchar_t; +typedef unsigned int wint_t; + +#define NULL ((void *)0) + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +#endif /* I386_STDDEF_H */ diff --git a/src/arch/x86/include/stdint.h b/src/arch/x86/include/stdint.h new file mode 100644 index 0000000000..b393cc10e0 --- /dev/null +++ b/src/arch/x86/include/stdint.h @@ -0,0 +1,77 @@ +#ifndef I386_STDINT_H +#define I386_STDINT_H + +#if defined(__GNUC__) +#define __HAVE_LONG_LONG__ 1 +#else +#define __HAVE_LONG_LONG__ 0 +#endif + +/* Exact integral types */ +typedef unsigned char uint8_t; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef unsigned int uint32_t; +typedef signed int int32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint64_t; +typedef signed long long int64_t; +#endif + +/* Small types */ +typedef unsigned char uint_least8_t; +typedef signed char int_least8_t; + +typedef unsigned short uint_least16_t; +typedef signed short int_least16_t; + +typedef unsigned int uint_least32_t; +typedef signed int int_least32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint_least64_t; +typedef signed long long int_least64_t; +#endif + +/* Fast Types */ +typedef unsigned char uint_fast8_t; +typedef signed char int_fast8_t; + +typedef unsigned int uint_fast16_t; +typedef signed int int_fast16_t; + +typedef unsigned int uint_fast32_t; +typedef signed int int_fast32_t; + +#if __HAVE_LONG_LONG__ +typedef unsigned long long uint_fast64_t; +typedef signed long long int_fast64_t; +#endif + +/* Types for `void *' pointers. */ +typedef int intptr_t; +typedef unsigned int uintptr_t; + +/* Largest integral types */ +#if __HAVE_LONG_LONG__ +typedef long long int intmax_t; +typedef unsigned long long uintmax_t; +#else +typedef long int intmax_t; +typedef unsigned long int uintmax_t; +#endif + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#if __HAVE_LONG_LONG__ +typedef uint64_t u64; +#endif + +#undef __HAVE_LONG_LONG__ + +#endif /* I386_STDINT_H */ |