source: mainline/kernel/arch/amd64/src/mm/page.c@ f74bbaf

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f74bbaf was 7cb567cd, checked in by Martin Decky <martin@…>, 19 years ago

map kernel pages explicitly as writable (this solves compatibility issues with Intel Core 2)
make VESA framebuffer initialization more robust

  • Property mode set to 100644
File size: 7.3 KB
RevLine 
[1141c1a]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
[1141c1a]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[06e1e95]29/** @addtogroup amd64mm
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[95498e5]35#include <arch/mm/page.h>
[6d7ffa65]36#include <genarch/mm/page_pt.h>
[95498e5]37#include <arch/mm/frame.h>
[d9f81af3]38#include <mm/page.h>
[db3341e]39#include <mm/frame.h>
[fc1e4f6]40#include <mm/as.h>
[db3341e]41#include <arch/interrupt.h>
42#include <arch/asm.h>
43#include <config.h>
44#include <memstr.h>
[fcfac420]45#include <interrupt.h>
[1ee9ced]46#include <print.h>
47#include <panic.h>
[93165be]48#include <align.h>
[1ee9ced]49
50/* Definitions for identity page mapper */
51pte_t helper_ptl1[512] __attribute__((aligned (PAGE_SIZE)));
52pte_t helper_ptl2[512] __attribute__((aligned (PAGE_SIZE)));
53pte_t helper_ptl3[512] __attribute__((aligned (PAGE_SIZE)));
54extern pte_t ptl_0; /* From boot.S */
55
56#define PTL1_PRESENT(ptl0, page) (!(GET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
57#define PTL2_PRESENT(ptl1, page) (!(GET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
58#define PTL3_PRESENT(ptl2, page) (!(GET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
59
60#define PTL1_ADDR(ptl0, page) ((pte_t *)PA2KA(GET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page))))
61#define PTL2_ADDR(ptl1, page) ((pte_t *)PA2KA(GET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page))))
62#define PTL3_ADDR(ptl2, page) ((pte_t *)PA2KA(GET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page))))
63
64#define SETUP_PTL1(ptl0, page, tgt) { \
[7f1c620]65 SET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
[1ee9ced]66 SET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
67 }
68#define SETUP_PTL2(ptl1, page, tgt) { \
[7f1c620]69 SET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
[1ee9ced]70 SET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
71 }
72#define SETUP_PTL3(ptl2, page, tgt) { \
[7f1c620]73 SET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
[1ee9ced]74 SET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
75 }
76#define SETUP_FRAME(ptl3, page, tgt) { \
[7f1c620]77 SET_FRAME_ADDRESS_ARCH(ptl3, PTL3_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \
[1ee9ced]78 SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
79 }
[c1982e45]80
81
[d9f81af3]82void page_arch_init(void)
83{
[7f1c620]84 uintptr_t cur;
[93165be]85 int i;
[7cb567cd]86 int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;
[db3341e]87
88 if (config.cpu_active == 1) {
[f5935ed]89 page_mapping_operations = &pt_mapping_operations;
[085d973]90
[db3341e]91 /*
92 * PA2KA(identity) mapping for all frames.
93 */
[95498e5]94 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
[93165be]95 /* Standard identity mapping */
[5fceec7]96 page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
[93165be]97 }
98 /* Upper kernel mapping
99 * - from zero to top of kernel (include bottom addresses
100 * because some are needed for init )
101 */
[deaa22f]102 for (cur = PA2KA_CODE(0); cur < config.base + config.kernel_size; cur += FRAME_SIZE)
[93165be]103 page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
[deaa22f]104
105 for (cur = config.stack_base; cur < config.stack_base + config.stack_size; cur += FRAME_SIZE)
106 page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
107
108 for (i = 0; i < init.cnt; i++) {
109 for (cur = init.tasks[i].addr; cur < init.tasks[i].addr + init.tasks[i].size; cur += FRAME_SIZE)
[93165be]110 page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags);
111 }
112
[8607db8]113 exc_register(14, "page_fault", (iroutine) page_fault);
[80bcaed]114 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
[7cb567cd]115 } else
[80bcaed]116 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
[d9f81af3]117}
[1ee9ced]118
[c1982e45]119
[1ee9ced]120/** Identity page mapper
121 *
122 * We need to map whole physical memory identically before the page subsystem
123 * is initializaed. This thing clears page table and fills in the specific
124 * items.
125 */
126void ident_page_fault(int n, istate_t *istate)
127{
[7f1c620]128 uintptr_t page;
129 static uintptr_t oldpage = 0;
[1ee9ced]130 pte_t *aptl_1, *aptl_2, *aptl_3;
131
132 page = read_cr2();
133 if (oldpage) {
134 /* Unmap old address */
135 aptl_1 = PTL1_ADDR(&ptl_0, oldpage);
136 aptl_2 = PTL2_ADDR(aptl_1, oldpage);
137 aptl_3 = PTL3_ADDR(aptl_2, oldpage);
138
139 SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
[5fceec7]140 if (KA2PA(aptl_3) == KA2PA(helper_ptl3))
[1ee9ced]141 SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
[5fceec7]142 if (KA2PA(aptl_2) == KA2PA(helper_ptl2))
[1ee9ced]143 SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
[5fceec7]144 if (KA2PA(aptl_1) == KA2PA(helper_ptl1))
[1ee9ced]145 SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
146 }
147 if (PTL1_PRESENT(&ptl_0, page))
148 aptl_1 = PTL1_ADDR(&ptl_0, page);
149 else {
150 SETUP_PTL1(&ptl_0, page, helper_ptl1);
151 aptl_1 = helper_ptl1;
152 }
153
154 if (PTL2_PRESENT(aptl_1, page))
155 aptl_2 = PTL2_ADDR(aptl_1, page);
156 else {
157 SETUP_PTL2(aptl_1, page, helper_ptl2);
158 aptl_2 = helper_ptl2;
159 }
160
161 if (PTL3_PRESENT(aptl_2, page))
162 aptl_3 = PTL3_ADDR(aptl_2, page);
163 else {
164 SETUP_PTL3(aptl_2, page, helper_ptl3);
165 aptl_3 = helper_ptl3;
166 }
167
168 SETUP_FRAME(aptl_3, page, page);
169
170 oldpage = page;
171}
172
[c1982e45]173
[1ee9ced]174void page_fault(int n, istate_t *istate)
175{
[7f1c620]176 uintptr_t page;
[567807b1]177 pf_access_t access;
[1ee9ced]178
179 page = read_cr2();
[567807b1]180
181 if (istate->error_word & PFERR_CODE_RSVD)
182 panic("Reserved bit set in page table entry.\n");
183
184 if (istate->error_word & PFERR_CODE_RW)
185 access = PF_ACCESS_WRITE;
186 else if (istate->error_word & PFERR_CODE_ID)
187 access = PF_ACCESS_EXEC;
188 else
189 access = PF_ACCESS_READ;
190
191 if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
[874621f]192 fault_if_from_uspace(istate, "Page fault: %#x", page);
193
[8607db8]194 decode_istate(n, istate);
[fbf7b4c]195 printf("Page fault address: %llx\n", page);
[1ee9ced]196 panic("page fault\n");
197 }
198}
[c1982e45]199
200
[7f1c620]201uintptr_t hw_map(uintptr_t physaddr, size_t size)
[c1982e45]202{
203 if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
204 panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
205
[7f1c620]206 uintptr_t virtaddr = PA2KA(last_frame);
[c1982e45]207 pfn_t i;
208 for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
[7cb567cd]209 page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
[c1982e45]210
211 last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
212
213 return virtaddr;
214}
[b45c443]215
[06e1e95]216/** @}
[b45c443]217 */
Note: See TracBrowser for help on using the repository browser.