MOS Source Code
Loading...
Searching...
No Matches
acpi.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
5#include "mos/mm/mm.hpp"
9
10#include <algorithm>
11#include <mos/mos_global.h>
12#include <mos/syslog/printk.hpp>
13#include <mos/types.hpp>
14#include <mos/x86/acpi/acpi.hpp>
15#include <mos/x86/acpi/madt.hpp>
16#include <mos/x86/cpu/cpu.hpp>
20#include <mos_stdlib.hpp>
21#include <mos_string.hpp>
22#include <stddef.h>
23
25
27 {},
28};
29
31
32#define do_verify_checksum(var, header, type) \
33 var = container_of(header, type, sdt_header); \
34 if (!verify_sdt_checksum(&(var)->sdt_header)) \
35 mos_panic(#type " checksum error");
36
37struct acpi_sysfs_item_t : mos::NamedType<"X86.ACPI.SysfsItem">
38{
40 size_t size;
42
43 acpi_sysfs_item_t(const char *name) : item(mos::string(name, 4))
44 {
45 }
46};
47
48static bool acpi_sysfs_mmap(sysfs_file_t *f, vmap_t *vmap, off_t offset)
49{
51 const ssize_t item_npages = ALIGN_UP_TO_PAGE(item->size) / MOS_PAGE_SIZE;
52 if (offset >= item_npages)
53 return false;
54
55 const size_t npages = std::min((ssize_t) vmap->npages, item_npages - offset); // limit to the number of pages in the item
56 mm_do_map(vmap->mmctx->pgd, vmap->vaddr, phyframe_pfn(item->pages), npages, vmap->vmflags, false); // no need to refcount
57 return true;
58}
59
60static bool acpi_sysfs_munmap(sysfs_file_t *f, vmap_t *vmap, bool *unmapped)
61{
63 mm_do_unmap(vmap->mmctx->pgd, vmap->vaddr, vmap->npages, false);
64 *unmapped = true;
65 return true;
66}
67
68static void register_sysfs_acpi_rsdp(const acpi_rsdp_t *rsdp)
69{
71 item->size = rsdp->length;
74 item->item.mem.size = item->size;
75 item->item.type = SYSFS_MEM;
77 if (!item->pages)
78 mos_panic("failed to allocate pages for ACPI table");
79
80 memcpy((void *) phyframe_va(item->pages), rsdp, rsdp->length);
81 pmm_ref(item->pages, true); // don't free the pages when the item is freed
82
84}
85
86static void register_sysfs_acpi_node(const char table_name[4], const acpi_sdt_header_t *header)
87{
88 acpi_sysfs_item_t *const item = mos::create<acpi_sysfs_item_t>(table_name);
89 item->size = header->length;
92 item->item.mem.size = item->size;
93 item->item.type = SYSFS_MEM;
95 if (!item->pages)
96 mos_panic("failed to allocate pages for ACPI table");
97
98 memcpy((void *) phyframe_va(item->pages), header, header->length);
99 pmm_ref(item->pages, true); // don't free the pages when the item is freed
100
102}
103
105{
106 u8 sum = 0;
107 for (u32 i = 0; i < tableHeader->length; i++)
108 sum += ((char *) tableHeader)[i];
109 return sum == 0;
110}
111
112static void do_handle_sdt_header(const acpi_sdt_header_t *const header)
113{
114 pr_dinfo2(x86_acpi, "%.4s at %p, size %u", header->signature, (void *) header, header->length);
115 register_sysfs_acpi_node(header->signature, header);
116
117 if (strncmp(header->signature, ACPI_SIGNATURE_FADT, 4) == 0)
118 {
119 const acpi_fadt_t *x86_acpi_fadt;
120 do_verify_checksum(x86_acpi_fadt, header, acpi_fadt_t);
121
122 const acpi_sdt_header_t *const dsdt = (acpi_sdt_header_t *) pa_va(x86_acpi_fadt->dsdt);
123 if (!verify_sdt_checksum(dsdt))
124 mos_panic("DSDT checksum error");
125 pr_dinfo2(x86_acpi, "DSDT at %p, size %u", (void *) dsdt, dsdt->length);
126 x86_acpi_dsdt = (ptr_t) dsdt;
127 register_sysfs_acpi_node("DSDT", dsdt);
128 }
129 else if (strncmp(header->signature, ACPI_SIGNATURE_MADT, 4) == 0)
130 {
132 }
133 else if (strncmp(header->signature, ACPI_SIGNATURE_HPET, 4) == 0)
134 {
135 const acpi_hpet_t *hpet;
136 do_verify_checksum(hpet, header, acpi_hpet_t);
137 const auto va = pa_va(hpet->addr.paddr);
138 pr_dinfo2(x86_acpi, "HPET PCI vendor id: %x", hpet->pci_vendor_id);
139 pr_dinfo2(x86_acpi, "HPET registers at address space %d, bit width %d, bit offset %d, access size %d, paddr %p", hpet->addr.addr_space, hpet->addr.bit_width,
140 hpet->addr.bit_offset, hpet->addr.access_size, (void *) va);
141
142 // set ENABLE_CNF to enable the HPET
143 *(volatile u32 *) (va + 0x010) |= 1 << 0;
144
145 for (int i = 0; i < 20; i++)
146 {
147 // read the HPET timer value
148 const u64 timer_value = *(volatile u64 *) (va + 0x0F0);
149 pr_dinfo2(x86_acpi, "HPET timer value: %llu", timer_value);
150 }
151 }
152}
153
154static void do_iterate_sdts(const acpi_rsdp_t *rsdp)
155{
156 if (rsdp->v1.revision == 0)
157 {
158 const acpi_sdt_header_t *rsdt_header = (acpi_sdt_header_t *) pa_va(rsdp->v1.rsdt_addr);
159 if (strncmp(rsdt_header->signature, "RSDT", 4) != 0)
160 mos_panic("RSDT signature mismatch");
161
162 const acpi_rsdt_t *x86_acpi_rsdt;
163 do_verify_checksum(x86_acpi_rsdt, rsdt_header, acpi_rsdt_t);
164
165 const size_t num_headers = (x86_acpi_rsdt->sdt_header.length - sizeof(acpi_sdt_header_t)) / sizeof(ptr32_t);
166 for (size_t i = 0; i < num_headers; i++)
167 {
168 const acpi_sdt_header_t *const header = (acpi_sdt_header_t *) pa_va(x86_acpi_rsdt->sdts[i]);
169 do_handle_sdt_header(header);
170 }
171 }
172 else if (rsdp->v1.revision == 2)
173 {
174 const acpi_sdt_header_t *xsdt_header = (acpi_sdt_header_t *) pa_va(rsdp->xsdt_addr);
175 if (strncmp(xsdt_header->signature, "XSDT", 4) != 0)
176 mos_panic("XSDT signature mismatch");
177
178 MOS_ASSERT_X(verify_sdt_checksum(xsdt_header), "acpi_xsdt_t checksum error");
179
180 const acpi_xsdt_t *x86_acpi_xsdt = container_of(xsdt_header, acpi_xsdt_t, sdt_header);
181
182 const size_t num_headers = (x86_acpi_xsdt->sdt_header.length - sizeof(acpi_sdt_header_t)) / sizeof(ptr64_t);
183 for (size_t i = 0; i < num_headers; i++)
184 {
185 const acpi_sdt_header_t *const header = (acpi_sdt_header_t *) pa_va(x86_acpi_xsdt->sdts[i]);
186 do_handle_sdt_header(header);
187 }
188 }
189 else
190 {
191 mos_panic("ACPI: RSDP revision %d not supported", rsdp->v1.revision);
192 }
193}
194
196{
197 pr_dinfo2(x86_acpi, "initializing ACPI with RSDP at %p", (void *) rsdp);
199 do_iterate_sdts(rsdp);
200}
201
203{
204 for (ptr_t addr = start; addr < start + size; addr += 0x10)
205 {
206 if (strncmp((const char *) addr, ACPI_SIGNATURE_RSDP, 8) == 0)
207 {
208 pr_dinfo2(x86_acpi, "ACPI: RSDP magic at %p", (void *) addr);
209 acpi_rsdp_t *rsdp = (acpi_rsdp_t *) addr;
210
211 // check the checksum
212 u8 sum = 0;
213 for (u32 i = 0; i < sizeof(acpi_rsdp_v1_t); i++)
214 sum += ((u8 *) rsdp)[i];
215
216 if (sum != 0)
217 {
218 pr_info2("ACPI: RSDP checksum failed");
219 continue;
220 }
221 pr_dinfo2(x86_acpi, "ACPI: oem: '%.6s', revision: %d", rsdp->v1.oem_id, rsdp->v1.revision);
222
223 if (rsdp->v1.revision != 0 && rsdp->v1.revision != 2)
224 mos_panic("ACPI: RSDP revision %d not supported", rsdp->v1.revision);
225
226 return rsdp;
227 }
228 }
229 return NULL;
230}
static bool acpi_sysfs_munmap(sysfs_file_t *f, vmap_t *vmap, bool *unmapped)
Definition acpi.cpp:60
static sysfs_dir_t __sysfs_acpi("acpi", acpi_sysfs_items, MOS_ARRAY_SIZE(acpi_sysfs_items))
static void register_sysfs_acpi_node(const char table_name[4], const acpi_sdt_header_t *header)
Definition acpi.cpp:86
#define do_verify_checksum(var, header, type)
Definition acpi.cpp:32
static void do_iterate_sdts(const acpi_rsdp_t *rsdp)
Definition acpi.cpp:154
void acpi_parse_rsdt(const acpi_rsdp_t *rsdp)
Definition acpi.cpp:195
static sysfs_item_t acpi_sysfs_items[]
Definition acpi.cpp:26
should_inline bool verify_sdt_checksum(const acpi_sdt_header_t *tableHeader)
Definition acpi.cpp:104
static void do_handle_sdt_header(const acpi_sdt_header_t *const header)
Definition acpi.cpp:112
static void register_sysfs_acpi_rsdp(const acpi_rsdp_t *rsdp)
Definition acpi.cpp:68
ptr_t x86_acpi_dsdt
Definition acpi.cpp:24
static bool acpi_sysfs_mmap(sysfs_file_t *f, vmap_t *vmap, off_t offset)
Definition acpi.cpp:48
const acpi_rsdp_t * acpi_find_rsdp(ptr_t start, size_t size)
Definition acpi.cpp:202
#define ACPI_SIGNATURE_RSDP
acpi_rsdp_v2_t acpi_rsdp_t
#define ACPI_SIGNATURE_HPET
#define ACPI_SIGNATURE_MADT
#define ACPI_SIGNATURE_FADT
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.hpp:12
#define MOS_PAGE_SIZE
Definition autoconf.h:6
MOSAPI s32 strncmp(const char *str1, const char *str2, size_t n)
#define phyframe_va(frame)
Definition mm.hpp:86
#define pa_va(pa)
Definition mm.hpp:87
phyframe_t * mm_get_free_pages(size_t npages)
Definition mm.cpp:47
#define pmm_ref(thing, npages)
Definition pmm.hpp:155
#define phyframe_pfn(frame)
Definition pmm.hpp:73
const acpi_madt_t * x86_acpi_madt
Definition madt.cpp:11
#define should_inline
Definition mos_global.h:37
#define ALIGN_UP_TO_PAGE(addr)
Definition mos_global.h:76
#define MOS_UNUSED(x)
Definition mos_global.h:65
T * create(Args &&...args)
Definition allocator.hpp:12
#define mos_panic(fmt,...)
Definition panic.hpp:51
static void * memcpy(void *s1, const void *s2, size_t n)
Definition pb_syshdr.h:90
#define NULL
Definition pb_syshdr.h:46
#define pr_info2(fmt,...)
Definition printk.hpp:36
#define pr_dinfo2(feat, fmt,...)
Definition printk.hpp:27
size_t size
Definition slab.cpp:32
const char * name
Definition slab.cpp:33
pgd_t pgd
Definition platform.hpp:64
generic_addr_t addr
acpi_rsdp_v1_t v1
ptr32_t sdts[]
acpi_sdt_header_t sdt_header
acpi_sysfs_item_t(const char *name)
Definition acpi.cpp:43
sysfs_item_t item
Definition acpi.cpp:39
phyframe_t * pages
Definition acpi.cpp:41
ptr64_t sdts[]
acpi_sdt_header_t sdt_header
sysfs_item_type_t type
Definition sysfs.hpp:23
bool(* mmap)(sysfs_file_t *file, vmap_t *vmap, off_t offset)
Definition sysfs.hpp:30
size_t size
Definition sysfs.hpp:32
bool(* munmap)(sysfs_file_t *file, vmap_t *vmap, bool *unmapped)
Definition sysfs.hpp:31
struct sysfs_item_t::@153140136221376072256077077307321051166012334217 mem
Definition mm.hpp:60
ptr_t vaddr
Definition mm.hpp:64
VMFlags vmflags
Definition mm.hpp:66
size_t npages
Definition mm.hpp:65
MMContext * mmctx
Definition mm.hpp:67
void sysfs_register_file(sysfs_dir_t *sysfs_dir, sysfs_item_t *item)
Register an entry in a sysfs directory.
Definition sysfs.cpp:382
sysfs_item_t * sysfs_file_get_item(sysfs_file_t *file)
Definition sysfs.cpp:115
@ SYSFS_MEM
memory-backed file
Definition sysfs.hpp:16
#define SYSFS_AUTOREGISTER(sysfs_name, sysfs_items)
#define f(_fmt)
Definition syslog.hpp:160
void mm_do_map(pgd_t top, ptr_t vaddr, pfn_t pfn, size_t n_pages, VMFlags flags, bool do_refcount)
Definition table_ops.cpp:23
void mm_do_unmap(pgd_t top, ptr_t vaddr, size_t n_pages, bool do_unref)
Definition table_ops.cpp:35
unsigned int u32
Definition types.h:17
ssize_t off_t
Definition types.h:80
unsigned int ptr32_t
Definition types.h:22
unsigned long ptr_t
Definition types.h:21
unsigned long long u64
Definition types.h:19
unsigned long long ptr64_t
Definition types.h:23
signed long ssize_t
Definition types.h:79
unsigned char u8
Definition types.h:15
#define container_of(ptr, type, member)
Definition types.hpp:33