blob: 28b253b2d33cba8981a2ff1b150a39555ed10ee1 [file] [log] [blame]
Kevin O'Connore54ee382009-07-26 19:33:13 -04001// Post memory manager (PMM) calls
2//
Kevin O'Connor9dea5902013-09-14 20:23:54 -04003// Copyright (C) 2009-2013 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connore54ee382009-07-26 19:33:13 -04004//
5// This file may be distributed under the terms of the GNU LGPLv3 license.
6
Kevin O'Connor9dea5902013-09-14 20:23:54 -04007#include "biosvar.h" // FUNC16
8#include "config.h" // CONFIG_*
Kevin O'Connor9dea5902013-09-14 20:23:54 -04009#include "malloc.h" // _malloc
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040010#include "output.h" // dprintf
Gerd Hoffmanna638acf2018-06-15 12:07:34 +020011#include "e820map.h" // struct e820entry
Kevin O'Connorb18557a2013-09-14 23:09:06 -040012#include "std/pmm.h" // PMM_SIGNATURE
Kevin O'Connor9dea5902013-09-14 20:23:54 -040013#include "string.h" // checksum
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040014#include "util.h" // pmm_init
Kevin O'Connorb9c6a962013-09-14 13:01:30 -040015#include "x86.h" // __ffs
Kevin O'Connor0bf92702009-08-01 11:45:37 -040016
Kevin O'Connore54ee382009-07-26 19:33:13 -040017extern struct pmmheader PMMHEADER;
18
Kevin O'Connore54ee382009-07-26 19:33:13 -040019#if CONFIG_PMM
Kevin O'Connor89a2f962013-02-18 23:36:03 -050020struct pmmheader PMMHEADER __aligned(16) VARFSEG = {
Kevin O'Connor6156afe2013-01-20 10:43:54 -050021 .signature = PMM_SIGNATURE,
Kevin O'Connore54ee382009-07-26 19:33:13 -040022 .version = 0x01,
23 .length = sizeof(PMMHEADER),
Kevin O'Connore54ee382009-07-26 19:33:13 -040024};
25#endif
26
Kevin O'Connore54ee382009-07-26 19:33:13 -040027// PMM - allocate
28static u32
29handle_pmm00(u16 *args)
30{
31 u32 length = *(u32*)&args[1], handle = *(u32*)&args[3];
32 u16 flags = args[5];
Kevin O'Connor0bf92702009-08-01 11:45:37 -040033 dprintf(3, "pmm00: length=%x handle=%x flags=%x\n"
Kevin O'Connore54ee382009-07-26 19:33:13 -040034 , length, handle, flags);
Kevin O'Connor0e9fd612009-08-22 21:31:58 -040035 struct zone_s *lowzone = &ZoneTmpLow, *highzone = &ZoneTmpHigh;
36 if (flags & 8) {
37 // Permanent memory request.
38 lowzone = &ZoneLow;
39 highzone = &ZoneHigh;
40 }
Kevin O'Connor0bf92702009-08-01 11:45:37 -040041 if (!length) {
42 // Memory size request
43 switch (flags & 3) {
44 default:
45 case 0:
46 return 0;
47 case 1:
Kevin O'Connor9dea5902013-09-14 20:23:54 -040048 return malloc_getspace(lowzone);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040049 case 2:
Kevin O'Connor9dea5902013-09-14 20:23:54 -040050 return malloc_getspace(highzone);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040051 case 3: {
Kevin O'Connor9dea5902013-09-14 20:23:54 -040052 u32 spacelow = malloc_getspace(lowzone);
53 u32 spacehigh = malloc_getspace(highzone);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040054 if (spacelow > spacehigh)
55 return spacelow;
56 return spacehigh;
57 }
58 }
59 }
60 u32 size = length * 16;
61 if ((s32)size <= 0)
62 return 0;
63 u32 align = MALLOC_MIN_ALIGN;
64 if (flags & 4) {
65 align = 1<<__ffs(size);
66 if (align < MALLOC_MIN_ALIGN)
67 align = MALLOC_MIN_ALIGN;
68 }
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040069 u32 data;
Kevin O'Connor0bf92702009-08-01 11:45:37 -040070 switch (flags & 3) {
71 default:
72 case 0:
73 return 0;
74 case 1:
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040075 data = malloc_palloc(lowzone, size, align);
Kevin O'Connor743c1572013-12-14 13:14:02 -050076 break;
Kevin O'Connor0bf92702009-08-01 11:45:37 -040077 case 2:
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040078 data = malloc_palloc(highzone, size, align);
Gerd Hoffmanna638acf2018-06-15 12:07:34 +020079 if (!data && (flags & 8)) {
80 /*
81 * We are out of meory. So go allocate from the (big)
82 * ZoneTmpHigh instead and reserve the block in the e820
83 * map so the OS will not override it. That way we can
84 * handle big permanent allocations without needing a big
85 * ZoneHigh.
86 */
87 data = malloc_palloc(&ZoneTmpHigh, size, align);
88 if (data)
89 e820_add(data, size, E820_RESERVED);
90 }
Kevin O'Connor743c1572013-12-14 13:14:02 -050091 break;
Kevin O'Connor0bf92702009-08-01 11:45:37 -040092 case 3: {
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040093 data = malloc_palloc(lowzone, size, align);
Kevin O'Connor743c1572013-12-14 13:14:02 -050094 if (!data)
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040095 data = malloc_palloc(highzone, size, align);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040096 }
97 }
Kevin O'Connor743c1572013-12-14 13:14:02 -050098 if (data && handle != MALLOC_DEFAULT_HANDLE)
99 malloc_sethandle(data, handle);
Kevin O'Connorfe6682d2015-09-22 14:45:25 -0400100 return data;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400101}
102
103// PMM - find
104static u32
105handle_pmm01(u16 *args)
106{
107 u32 handle = *(u32*)&args[1];
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400108 dprintf(3, "pmm01: handle=%x\n", handle);
Kevin O'Connor9dea5902013-09-14 20:23:54 -0400109 if (handle == MALLOC_DEFAULT_HANDLE)
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400110 return 0;
Kevin O'Connorfe6682d2015-09-22 14:45:25 -0400111 return malloc_findhandle(handle);
Kevin O'Connore54ee382009-07-26 19:33:13 -0400112}
113
114// PMM - deallocate
115static u32
116handle_pmm02(u16 *args)
117{
118 u32 buffer = *(u32*)&args[1];
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400119 dprintf(3, "pmm02: buffer=%x\n", buffer);
Kevin O'Connorfe6682d2015-09-22 14:45:25 -0400120 int ret = malloc_pfree(buffer);
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400121 if (ret)
122 // Error
123 return 1;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400124 return 0;
125}
126
127static u32
128handle_pmmXX(u16 *args)
129{
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400130 return PMM_FUNCTION_NOT_SUPPORTED;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400131}
132
Kevin O'Connor533b6282011-07-16 13:13:12 -0400133u32 VISIBLE32INIT
Kevin O'Connore54ee382009-07-26 19:33:13 -0400134handle_pmm(u16 *args)
135{
Kevin O'Connor1313b782011-07-16 13:39:26 -0400136 ASSERT32FLAT();
Kevin O'Connore54ee382009-07-26 19:33:13 -0400137 if (! CONFIG_PMM)
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400138 return PMM_FUNCTION_NOT_SUPPORTED;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400139
140 u16 arg1 = args[0];
141 dprintf(DEBUG_HDL_pmm, "pmm call arg1=%x\n", arg1);
142
Kevin O'Connor533b6282011-07-16 13:13:12 -0400143 u32 ret;
144 switch (arg1) {
145 case 0x00: ret = handle_pmm00(args); break;
146 case 0x01: ret = handle_pmm01(args); break;
147 case 0x02: ret = handle_pmm02(args); break;
148 default: ret = handle_pmmXX(args); break;
149 }
150
Kevin O'Connor533b6282011-07-16 13:13:12 -0400151 return ret;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400152}
153
Kevin O'Connore54ee382009-07-26 19:33:13 -0400154void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500155pmm_init(void)
Kevin O'Connore54ee382009-07-26 19:33:13 -0400156{
157 if (! CONFIG_PMM)
158 return;
159
160 dprintf(3, "init PMM\n");
161
Kevin O'Connor6156afe2013-01-20 10:43:54 -0500162 PMMHEADER.entry = FUNC16(entry_pmm);
Kevin O'Connore54ee382009-07-26 19:33:13 -0400163 PMMHEADER.checksum -= checksum(&PMMHEADER, sizeof(PMMHEADER));
164}
165
166void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500167pmm_prepboot(void)
Kevin O'Connore54ee382009-07-26 19:33:13 -0400168{
169 if (! CONFIG_PMM)
170 return;
171
172 dprintf(3, "finalize PMM\n");
173
174 PMMHEADER.signature = 0;
Kevin O'Connor6156afe2013-01-20 10:43:54 -0500175 PMMHEADER.entry.segoff = 0;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400176}